1 /*
2  * Copyright (C) 2016 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.aware;
18 
19 import static android.Manifest.permission.ACCESS_WIFI_STATE;
20 import static android.net.wifi.WifiAvailableChannel.OP_MODE_WIFI_AWARE;
21 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128;
22 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_RESUME_INTERNAL_ERROR;
23 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_RESUME_INVALID_SESSION;
24 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_RESUME_REDUNDANT_REQUEST;
25 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_SUSPEND_CANNOT_SUSPEND;
26 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_SUSPEND_INTERNAL_ERROR;
27 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_SUSPEND_INVALID_SESSION;
28 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_SUSPEND_REDUNDANT_REQUEST;
29 
30 import static com.android.server.wifi.WifiSettingsConfigStore.D2D_ALLOWED_WHEN_INFRA_STA_DISABLED;
31 import static com.android.server.wifi.aware.WifiAwareMetrics.convertNanStatusCodeToWifiStatsLogEnum;
32 import static com.android.server.wifi.hal.WifiNanIface.NanStatusCode.NOT_SUPPORTED;
33 import static com.android.server.wifi.hal.WifiNanIface.NanStatusCode.NO_CONNECTION;
34 import static com.android.server.wifi.hal.WifiNanIface.NanStatusCode.REDUNDANT_REQUEST;
35 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_CAPABILITIES;
36 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED;
37 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_API_UNKNOWN;
38 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_CONFIG_REQUEST;
39 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_CREATE_DATA_INTERFACE_REQUEST;
40 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_DELETE_DATA_INTERFACE_REQUEST;
41 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_DISABLE_REQUEST;
42 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_ENABLE_REQUEST;
43 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_GET_CAPABILITIES_REQUEST;
44 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_INITIATE_BOOTSTRAPPING_REQUEST;
45 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_INITIATE_DATA_PATH_REQUEST;
46 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_INITIATE_PAIRING_REQUEST;
47 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESPOND_TO_BOOTSTRAPPING_INDICATION_REQUEST;
48 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESPOND_TO_DATA_PATH_INDICATION_REQUEST;
49 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESPOND_TO_PAIRING_INDICATION_REQUEST;
50 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESUME_REQUEST;
51 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_START_PUBLISH_REQUEST;
52 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_START_SUBSCRIBE_REQUEST;
53 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_SUSPEND_REQUEST;
54 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_TERMINATE_DATA_PATH_REQUEST;
55 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_TERMINATE_PAIRING_REQUEST;
56 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_TRANSMIT_FOLLOW_UP_REQUEST;
57 
58 import android.annotation.NonNull;
59 import android.annotation.Nullable;
60 import android.app.StatsManager;
61 import android.content.AttributionSource;
62 import android.content.BroadcastReceiver;
63 import android.content.Context;
64 import android.content.Intent;
65 import android.content.IntentFilter;
66 import android.hardware.wifi.V1_0.WifiStatusCode;
67 import android.location.LocationManager;
68 import android.net.MacAddress;
69 import android.net.wifi.IBooleanListener;
70 import android.net.wifi.IIntegerListener;
71 import android.net.wifi.IListListener;
72 import android.net.wifi.OuiKeyedData;
73 import android.net.wifi.WifiAvailableChannel;
74 import android.net.wifi.WifiManager;
75 import android.net.wifi.WifiScanner;
76 import android.net.wifi.aware.AwarePairingConfig;
77 import android.net.wifi.aware.AwareParams;
78 import android.net.wifi.aware.AwareResources;
79 import android.net.wifi.aware.Characteristics;
80 import android.net.wifi.aware.ConfigRequest;
81 import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback;
82 import android.net.wifi.aware.IWifiAwareEventCallback;
83 import android.net.wifi.aware.IWifiAwareMacAddressProvider;
84 import android.net.wifi.aware.IdentityChangedListener;
85 import android.net.wifi.aware.MacAddrMapping;
86 import android.net.wifi.aware.PublishConfig;
87 import android.net.wifi.aware.SubscribeConfig;
88 import android.net.wifi.aware.WifiAwareChannelInfo;
89 import android.net.wifi.aware.WifiAwareDataPathSecurityConfig;
90 import android.net.wifi.aware.WifiAwareManager;
91 import android.net.wifi.aware.WifiAwareNetworkSpecifier;
92 import android.net.wifi.util.HexEncoding;
93 import android.os.Bundle;
94 import android.os.Handler;
95 import android.os.Looper;
96 import android.os.Message;
97 import android.os.PowerManager;
98 import android.os.Process;
99 import android.os.RemoteException;
100 import android.os.SystemClock;
101 import android.os.UserHandle;
102 import android.os.WorkSource;
103 import android.text.TextUtils;
104 import android.util.ArraySet;
105 import android.util.Log;
106 import android.util.Pair;
107 import android.util.SparseArray;
108 import android.util.StatsEvent;
109 
110 import com.android.internal.annotations.VisibleForTesting;
111 import com.android.internal.util.MessageUtils;
112 import com.android.internal.util.StateMachine;
113 import com.android.internal.util.WakeupMessage;
114 import com.android.modules.utils.BasicShellCommandHandler;
115 import com.android.modules.utils.HandlerExecutor;
116 import com.android.modules.utils.build.SdkLevel;
117 import com.android.server.wifi.Clock;
118 import com.android.server.wifi.HalDeviceManager;
119 import com.android.server.wifi.InterfaceConflictManager;
120 import com.android.server.wifi.RunnerState;
121 import com.android.server.wifi.WifiGlobals;
122 import com.android.server.wifi.WifiInjector;
123 import com.android.server.wifi.WifiSettingsConfigStore;
124 import com.android.server.wifi.aware.PairingConfigManager.PairingSecurityAssociationInfo;
125 import com.android.server.wifi.hal.WifiNanIface.NanStatusCode;
126 import com.android.server.wifi.proto.WifiStatsLog;
127 import com.android.server.wifi.util.NetdWrapper;
128 import com.android.server.wifi.util.WaitingState;
129 import com.android.server.wifi.util.WifiPermissionsUtil;
130 import com.android.server.wifi.util.WifiPermissionsWrapper;
131 import com.android.wifi.flags.FeatureFlags;
132 import com.android.wifi.resources.R;
133 
134 import org.json.JSONException;
135 import org.json.JSONObject;
136 
137 import java.io.FileDescriptor;
138 import java.io.PrintWriter;
139 import java.util.ArrayList;
140 import java.util.Arrays;
141 import java.util.HashMap;
142 import java.util.Iterator;
143 import java.util.LinkedHashMap;
144 import java.util.List;
145 import java.util.Map;
146 import java.util.Set;
147 import java.util.concurrent.Executor;
148 import java.util.function.Consumer;
149 
150 /**
151  * Manages the state of the Wi-Fi Aware system service.
152  */
153 public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShellCommand {
154     private static final String TAG = "WifiAwareStateManager";
155     private boolean mVdbg = false; // STOPSHIP if true - for detailed state machine
156     private boolean mVerboseLoggingEnabled = false;
157 
158     @VisibleForTesting
159     public static final String HAL_COMMAND_TIMEOUT_TAG = TAG + " HAL Command Timeout";
160 
161     @VisibleForTesting
162     public static final String HAL_SEND_MESSAGE_TIMEOUT_TAG = TAG + " HAL Send Message Timeout";
163 
164     @VisibleForTesting
165     public static final String HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG =
166             TAG + " HAL Data Path Confirm Timeout";
167     @VisibleForTesting
168     public static final String HAL_PAIRING_CONFIRM_TIMEOUT_TAG =
169             TAG + " HAL Pairing Confirm Timeout";
170     @VisibleForTesting
171     public static final String HAL_BOOTSTRAPPING_CONFIRM_TIMEOUT_TAG =
172             TAG + " HAL Bootstrapping Confirm Timeout";
173 
174     public static final int NAN_PAIRING_REQUEST_TYPE_SETUP = 0;
175     public static final int NAN_PAIRING_REQUEST_TYPE_VERIFICATION = 1;
176     public static final int NAN_PAIRING_AKM_SAE = 0;
177     public static final int NAN_PAIRING_AKM_PASN = 1;
178     public static final int NAN_BOOTSTRAPPING_ACCEPT = 0;
179     public static final int NAN_BOOTSTRAPPING_REJECT = 1;
180     public static final int NAN_BOOTSTRAPPING_COMEBACK = 2;
181 
182 
183     public static final int NAN_PARAM_NOT_SET = -1;
184 
185     public static final int INSTANT_MODE_DISABLED = 0;
186     public static final int INSTANT_MODE_24GHZ = 1;
187     public static final int INSTANT_MODE_5GHZ = 3;
188 
189     /*
190      * State machine message types. There are sub-types for the messages (except for TIMEOUTs).
191      * Format:
192      * - Message.arg1: contains message sub-type
193      * - Message.arg2: contains transaction ID for RESPONSE & RESPONSE_TIMEOUT
194      */
195     private static final int MESSAGE_TYPE_COMMAND = 1;
196     private static final int MESSAGE_TYPE_RESPONSE = 2;
197     private static final int MESSAGE_TYPE_NOTIFICATION = 3;
198     private static final int MESSAGE_TYPE_RESPONSE_TIMEOUT = 4;
199     private static final int MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT = 5;
200     private static final int MESSAGE_TYPE_DATA_PATH_TIMEOUT = 6;
201     private static final int MESSAGE_TYPE_PAIRING_TIMEOUT = 7;
202     private static final int MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT = 8;
203 
204     /*
205      * Message sub-types:
206      */
207     private static final int COMMAND_TYPE_CONNECT = 100;
208     private static final int COMMAND_TYPE_DISCONNECT = 101;
209     private static final int COMMAND_TYPE_TERMINATE_SESSION = 102;
210     private static final int COMMAND_TYPE_PUBLISH = 103;
211     private static final int COMMAND_TYPE_UPDATE_PUBLISH = 104;
212     private static final int COMMAND_TYPE_SUBSCRIBE = 105;
213     private static final int COMMAND_TYPE_UPDATE_SUBSCRIBE = 106;
214     private static final int COMMAND_TYPE_ENQUEUE_SEND_MESSAGE = 107;
215     private static final int COMMAND_TYPE_ENABLE_USAGE = 108;
216     private static final int COMMAND_TYPE_DISABLE_USAGE = 109;
217     private static final int COMMAND_TYPE_GET_CAPABILITIES = 111;
218     private static final int COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES = 113;
219     private static final int COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE = 114;
220     private static final int COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE = 115;
221     private static final int COMMAND_TYPE_INITIATE_DATA_PATH_SETUP = 116;
222     private static final int COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST = 117;
223     private static final int COMMAND_TYPE_END_DATA_PATH = 118;
224     private static final int COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE = 119;
225     private static final int COMMAND_TYPE_RECONFIGURE = 120;
226     private static final int COMMAND_TYPE_DELAYED_INITIALIZATION = 121;
227     private static final int COMMAND_TYPE_GET_AWARE = 122;
228     private static final int COMMAND_TYPE_RELEASE_AWARE = 123;
229     private static final int COMMAND_TYPE_DISABLE = 124;
230     private static final int COMMAND_TYPE_INITIATE_PAIRING_REQUEST = 125;
231     private static final int COMMAND_TYPE_RESPONSE_PAIRING_REQUEST = 126;
232     private static final int COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST = 127;
233     private static final int COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST = 128;
234     private static final int COMMAND_TYPE_SUSPEND_SESSION = 129;
235     private static final int COMMAND_TYPE_RESUME_SESSION = 130;
236     private static final int COMMAND_TYPE_END_PAIRING = 131;
237 
238     private static final int RESPONSE_TYPE_ON_CONFIG_SUCCESS = 200;
239     private static final int RESPONSE_TYPE_ON_CONFIG_FAIL = 201;
240     private static final int RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS = 202;
241     private static final int RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL = 203;
242     private static final int RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS = 204;
243     private static final int RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL = 205;
244     private static final int RESPONSE_TYPE_ON_CAPABILITIES_UPDATED = 206;
245     private static final int RESPONSE_TYPE_ON_CREATE_INTERFACE = 207;
246     private static final int RESPONSE_TYPE_ON_DELETE_INTERFACE = 208;
247     private static final int RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS = 209;
248     private static final int RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL = 210;
249     private static final int RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST = 211;
250     private static final int RESPONSE_TYPE_ON_END_DATA_PATH = 212;
251     private static final int RESPONSE_TYPE_ON_DISABLE = 213;
252     private static final int RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS = 214;
253     private static final int RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL = 215;
254     private static final int RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS = 216;
255     private static final int RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL = 217;
256     private static final int RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS = 218;
257     private static final int RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL = 219;
258     private static final int RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS = 220;
259     private static final int RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL = 221;
260     private static final int RESPONSE_TYPE_ON_SUSPEND = 222;
261     private static final int RESPONSE_TYPE_ON_RESUME = 223;
262     private static final int RESPONSE_TYPE_ON_END_PAIRING = 224;
263 
264     private static final int NOTIFICATION_TYPE_INTERFACE_CHANGE = 301;
265     private static final int NOTIFICATION_TYPE_CLUSTER_CHANGE = 302;
266     private static final int NOTIFICATION_TYPE_MATCH = 303;
267     private static final int NOTIFICATION_TYPE_SESSION_TERMINATED = 304;
268     private static final int NOTIFICATION_TYPE_MESSAGE_RECEIVED = 305;
269     private static final int NOTIFICATION_TYPE_AWARE_DOWN = 306;
270     private static final int NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS = 307;
271     private static final int NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL = 308;
272     private static final int NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST = 309;
273     private static final int NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM = 310;
274     private static final int NOTIFICATION_TYPE_ON_DATA_PATH_END = 311;
275     private static final int NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE = 312;
276     private static final int NOTIFICATION_TYPE_MATCH_EXPIRED = 313;
277     private static final int NOTIFICATION_TYPE_ON_PAIRING_REQUEST = 314;
278     private static final int NOTIFICATION_TYPE_ON_PAIRING_CONFIRM = 315;
279     private static final int NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST = 316;
280     private static final int NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM = 317;
281     private static final int NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED = 318;
282 
283     private static final SparseArray<String> sSmToString = MessageUtils.findMessageNames(
284             new Class[]{WifiAwareStateManager.class},
285             new String[]{"MESSAGE_TYPE", "COMMAND_TYPE", "RESPONSE_TYPE", "NOTIFICATION_TYPE"});
286 
287     /*
288      * Keys used when passing (some) arguments to the Handler thread (too many
289      * arguments to pass in the short-cut Message members).
290      */
291     private static final String MESSAGE_BUNDLE_KEY_SESSION_TYPE = "session_type";
292     private static final String MESSAGE_BUNDLE_KEY_SESSION_ID = "session_id";
293     private static final String MESSAGE_BUNDLE_KEY_CONFIG = "config";
294     private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
295     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID = "message_peer_id";
296     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ID = "message_id";
297     private static final String MESSAGE_BUNDLE_KEY_SSI_DATA = "ssi_data";
298     private static final String MESSAGE_BUNDLE_KEY_FILTER_DATA = "filter_data";
299     private static final String MESSAGE_BUNDLE_KEY_MAC_ADDRESS = "mac_address";
300     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_DATA = "message_data";
301     private static final String MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID = "req_instance_id";
302     private static final String MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME = "message_queue_time";
303     private static final String MESSAGE_BUNDLE_KEY_RETRY_COUNT = "retry_count";
304     private static final String MESSAGE_BUNDLE_KEY_SUCCESS_FLAG = "success_flag";
305     private static final String MESSAGE_BUNDLE_KEY_STATUS_CODE = "status_code";
306     private static final String MESSAGE_BUNDLE_KEY_INTERFACE_NAME = "interface_name";
307     private static final String MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE = "channel_request_type";
308     private static final String MESSAGE_BUNDLE_KEY_CHANNEL = "channel";
309     private static final String MESSAGE_BUNDLE_KEY_PEER_ID = "peer_id";
310     private static final String MESSAGE_BUNDLE_KEY_UID = "uid";
311     private static final String MESSAGE_BUNDLE_KEY_PID = "pid";
312     private static final String MESSAGE_BUNDLE_KEY_CALLING_PACKAGE = "calling_package";
313     private static final String MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID = "calling_feature_id";
314     private static final String MESSAGE_BUNDLE_KEY_SENT_MESSAGE = "send_message";
315     private static final String MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ = "message_arrival_seq";
316     private static final String MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE = "notify_identity_chg";
317     private static final String MESSAGE_BUNDLE_KEY_SCID = "scid";
318     private static final String MESSAGE_BUNDLE_KEY_CIPHER_SUITE = "cipher_suite";
319     private static final String MESSAGE_BUNDLE_KEY_OOB = "out_of_band";
320     private static final String MESSAGE_RANGING_INDICATION = "ranging_indication";
321     private static final String MESSAGE_RANGE_MM = "range_mm";
322     private static final String MESSAGE_BUNDLE_KEY_NDP_IDS = "ndp_ids";
323     private static final String MESSAGE_BUNDLE_KEY_APP_INFO = "app_info";
324     private static final String MESSAGE_BUNDLE_KEY_ACCEPT_STATE = "accept_state";
325     private static final String MESSAGE_BUNDLE_KEY_NONCE = "nonce";
326     private static final String MESSAGE_BUNDLE_KEY_TAG = "tag";
327     private static final String MESSAGE_BUNDLE_KEY_PAIRING_CONFIG = "pairing_config";
328     private static final String MESSAGE_BUNDLE_KEY_PAIRING_PASSWORD = "pairing_password";
329     private static final String MESSAGE_BUNDLE_KEY_PAIRING_ALIAS = "pairing_alias";
330     private static final String MESSAGE_BUNDLE_KEY_PAIRING_TYPE = "pairing_type";
331     private static final String MESSAGE_BUNDLE_KEY_PAIRING_AKM = "pairing_akm";
332     private static final String MESSAGE_BUNDLE_KEY_PAIRING_CIPHER_SUITE = "pairing_cipher_suite";
333     private static final String MESSAGE_BUNDLE_KEY_PAIRING_PMK = "pairing_pmk";
334     private static final String MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID = "pairing_request_id";
335     private static final String MESSAGE_BUNDLE_KEY_PAIRING_ACCEPT = "pairing_accept";
336     private static final String MESSAGE_BUNDLE_KEY_PAIRING_CACHE = "pairing_cache";
337     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD = "bootstrapping_method";
338     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID =
339             "bootstrapping_request_id";
340     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_ACCEPT = "bootstrapping_accept";
341     private static final String MESSAGE_BUNDLE_KEY_AWARE_OFFLOAD = "aware_offload";
342     private static final String MESSAGE_BUNDLE_KEY_RE_ENABLE_AWARE_FROM_OFFLOAD =
343             "aware_re_enable_from_offload";
344     private static final String MESSAGE_BUNDLE_KEY_SUSPENSION_MODE = "suspension_mode";
345 
346     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_RESPONSE_CODE =
347             "bootstrapping_response_state";
348     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_DELAY =
349             "bootstrapping_come_back_delay";
350     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_COOKIE =
351             "bootstrapping_come_back_cookie";
352     private static final String MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_IS_COME_BACK_REQUEST =
353             "bootstrapping_is_come_back";
354     private static final String MESSAGE_BUNDLE_KEY_CALLER_TYPE = "caller_type";
355     private static final String MESSAGE_BUNDLE_KEY_VENDOR_DATA = "vendor_data";
356     private WifiAwareNativeApi mWifiAwareNativeApi;
357     private WifiAwareNativeManager mWifiAwareNativeManager;
358 
359     /*
360      * Asynchronous access with no lock
361      */
362     private volatile boolean mUsageEnabled = false;
363 
364     /*
365      * Synchronous access: state is only accessed through the state machine
366      * handler thread: no need to use a lock.
367      */
368     private Context mContext;
369     private WifiAwareMetrics mAwareMetrics;
370     private WifiPermissionsUtil mWifiPermissionsUtil;
371     private volatile Capabilities mCapabilities;
372     private volatile Characteristics mCharacteristics = null;
373     private WifiAwareStateMachine mSm;
374     public WifiAwareDataPathStateManager mDataPathMgr;
375     private PowerManager mPowerManager;
376     private InterfaceConflictManager mInterfaceConflictMgr;
377     private WifiManager mWifiManager;
378     private Handler mHandler;
379     private final WifiInjector mWifiInjector;
380     private final PairingConfigManager mPairingConfigManager;
381     private final WifiSettingsConfigStore mSettingsConfigStore;
382     private final WifiGlobals mWifiGlobals;
383     private final FeatureFlags mFeatureFlags;
384 
385     private final SparseArray<WifiAwareClientState> mClients = new SparseArray<>();
386     private ConfigRequest mCurrentAwareConfiguration = null;
387     private boolean mCurrentIdentityNotification = false;
388     private boolean mCurrentRangingEnabled = false;
389     private boolean mInstantCommModeGlobalEnable = false;
390     private int mOverrideInstantMode = INSTANT_MODE_DISABLED;
391     private int mInstantCommModeClientRequest = INSTANT_MODE_DISABLED;
392     private int mClusterIdInt = NAN_PARAM_NOT_SET; // -1 is not set.
393     private static final int AWARE_BAND_2_INSTANT_COMMUNICATION_CHANNEL_FREQ = 2437; // Channel 6
394     private int mAwareBand5InstantCommunicationChannelFreq =
395             NAN_PARAM_NOT_SET; // -1 is not set, 0 is unsupported.
396     private static final int AWARE_BAND_5_INSTANT_COMMUNICATION_CHANNEL_FREQ_CHANNEL_149 = 5745;
397     private static final int AWARE_BAND_5_INSTANT_COMMUNICATION_CHANNEL_FREQ_CHANNEL_44 = 5220;
398 
399     private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0};
400     private byte[] mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC;
401     private byte[] mClusterId = ALL_ZERO_MAC;
402     private int mClusterEventType = -1;
403     // Flag to help defer the connect request when disable Aware is not finished, to prevent race
404     // condition.
405     private boolean mAwareIsDisabling = false;
406     private final SparseArray<PairingInfo> mPairingRequest = new SparseArray<>();
407     private final SparseArray<BootStrppingInfo> mBootstrappingRequest = new SparseArray<>();
408     private WifiAwarePullAtomCallback mWifiAwarePullAtomCallback = null;
409 
410     private long mStartTime;
411 
412     private static class PairingInfo {
413         public final int mClientId;
414         public final int mSessionId;
415         public final int mPeerId;
416         public final String mAlias;
417 
PairingInfo(int clientId, int sessionId, int peerId, String alias)418         PairingInfo(int clientId, int sessionId, int peerId, String alias) {
419             mClientId = clientId;
420             mSessionId = sessionId;
421             mPeerId = peerId;
422             mAlias = alias;
423         }
424     }
425 
426     private static class BootStrppingInfo {
427         public final int mClientId;
428         public final int mSessionId;
429         public final int mPeerId;
430         public final int mMethod;
431         public final boolean mIsComeBackFollowUp;
432 
BootStrppingInfo(int clientId, int sessionId, int peerId, int method, boolean isComeBackFollowUp)433         BootStrppingInfo(int clientId, int sessionId, int peerId, int method,
434                 boolean isComeBackFollowUp) {
435             mClientId = clientId;
436             mSessionId = sessionId;
437             mPeerId = peerId;
438             mMethod = method;
439             mIsComeBackFollowUp = isComeBackFollowUp;
440         }
441     }
442 
WifiAwareStateManager(WifiInjector wifiInjector, PairingConfigManager pairingConfigManager)443     public WifiAwareStateManager(WifiInjector wifiInjector,
444             PairingConfigManager pairingConfigManager) {
445         mWifiInjector = wifiInjector;
446         mPairingConfigManager = pairingConfigManager;
447         mWifiGlobals =  mWifiInjector.getWifiGlobals();
448         mFeatureFlags = mWifiInjector.getDeviceConfigFacade().getFeatureFlags();
449         mSettingsConfigStore = mWifiInjector.getSettingsConfigStore();
450         onReset();
451     }
452 
453     /**
454      * Enable/Disable verbose logging.
455      */
enableVerboseLogging(boolean verboseEnabled, boolean halVerboseLogging, boolean vDbg)456     public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseLogging,
457             boolean vDbg) {
458         mVerboseLoggingEnabled = verboseEnabled;
459         mDataPathMgr.enableVerboseLogging(verboseEnabled, vDbg);
460         mSm.setDbg(halVerboseLogging);
461         mVdbg = vDbg;
462     }
463 
464     /**
465      * Inject references to other manager objects. Needed to resolve
466      * circular dependencies and to allow mocking.
467      */
setNative(WifiAwareNativeManager wifiAwareNativeManager, WifiAwareNativeApi wifiAwareNativeApi)468     public void setNative(WifiAwareNativeManager wifiAwareNativeManager,
469             WifiAwareNativeApi wifiAwareNativeApi) {
470         mWifiAwareNativeManager = wifiAwareNativeManager;
471         mWifiAwareNativeApi = wifiAwareNativeApi;
472     }
473 
474     /*
475      * parameters settable through shell command
476      */
477     public static final String PARAM_ON_IDLE_DISABLE_AWARE = "on_idle_disable_aware";
478     public static final int PARAM_ON_IDLE_DISABLE_AWARE_DEFAULT = 1; // 0 = false, 1 = true
479 
480     private final Map<String, Integer> mSettableParameters = new HashMap<>();
481 
482     private final Set<String> mOpportunisticSet = new ArraySet<>();
483 
484     /**
485      * Interpreter of adb shell command 'adb shell wifiaware native_api ...'.
486      *
487      * @return -1 if parameter not recognized or invalid value, 0 otherwise.
488      */
489     @Override
onCommand(BasicShellCommandHandler parentShell)490     public int onCommand(BasicShellCommandHandler parentShell) {
491         final PrintWriter pw_err = parentShell.getErrPrintWriter();
492         final PrintWriter pw_out = parentShell.getOutPrintWriter();
493 
494         String subCmd = parentShell.getNextArgRequired();
495         switch (subCmd) {
496             case "set": {
497                 String name = parentShell.getNextArgRequired();
498                 if (!mSettableParameters.containsKey(name)) {
499                     pw_err.println("Unknown parameter name -- '" + name + "'");
500                     return -1;
501                 }
502 
503                 String valueStr = parentShell.getNextArgRequired();
504                 int value;
505                 try {
506                     value = Integer.valueOf(valueStr);
507                 } catch (NumberFormatException e) {
508                     pw_err.println("Can't convert value to integer -- '" + valueStr + "'");
509                     return -1;
510                 }
511                 mSettableParameters.put(name, value);
512                 return 0;
513             }
514             case "get": {
515                 String name = parentShell.getNextArgRequired();
516                 if (!mSettableParameters.containsKey(name)) {
517                     pw_err.println("Unknown parameter name -- '" + name + "'");
518                     return -1;
519                 }
520 
521                 pw_out.println((int) mSettableParameters.get(name));
522                 return 0;
523             }
524             case "get_capabilities": {
525                 if (mCapabilities != null) {
526                     try {
527                         pw_out.println(mCapabilities.toJSON().toString());
528                     } catch (JSONException e) {
529                         Log.e(TAG, "onCommand: get_capabilities e=" + e);
530                     }
531                 }
532                 return 0;
533             }
534             case "get_aware_resources": {
535                 if (!SdkLevel.isAtLeastS()) {
536                     return -1;
537                 }
538                 JSONObject j = new JSONObject();
539                 AwareResources resources = getAvailableAwareResources();
540                 if (resources != null) {
541                     try {
542                         j.put("numOfAvailableNdps", resources.getAvailableDataPathsCount());
543                         j.put("numOfAvailablePublishSessions",
544                                 resources.getAvailablePublishSessionsCount());
545                         j.put("numOfAvailableSubscribeSessions",
546                                 resources.getAvailableSubscribeSessionsCount());
547                     } catch (JSONException e) {
548                         Log.e(TAG, "onCommand: get_aware_resources e=" + e);
549                     }
550                 }
551                 pw_out.println(j.toString());
552                 return 0;
553             }
554             case "allow_ndp_any": {
555                 String flag = parentShell.getNextArgRequired();
556                 if (mDataPathMgr == null) {
557                     pw_err.println("Null Aware data-path manager - can't configure");
558                     return -1;
559                 }
560                 if (TextUtils.equals("true", flag)) {
561                     mDataPathMgr.mAllowNdpResponderFromAnyOverride = true;
562                     return 0;
563                 } else  if (TextUtils.equals("false", flag)) {
564                     mDataPathMgr.mAllowNdpResponderFromAnyOverride = false;
565                     return 0;
566                 } else {
567                     pw_err.println(
568                             "Unknown configuration flag for 'allow_ndp_any' - true|false expected"
569                                     + " -- '"
570                                     + flag + "'");
571                     return -1;
572                 }
573             }
574             case "get_instant_communication_channel": {
575                 String arg = parentShell.getNextArgRequired();
576                 int band;
577                 if (TextUtils.equals(arg, "2G")) {
578                     band = WifiScanner.WIFI_BAND_24_GHZ;
579                 } else if (TextUtils.equals(arg, "5G")) {
580                     band = WifiScanner.WIFI_BAND_5_GHZ;
581                 } else {
582                     pw_err.println("Unknown band -- " + arg);
583                     return -1;
584                 }
585                 List<WifiAvailableChannel> channels = mWifiInjector.getWifiThreadRunner().call(
586                         () -> mWifiInjector.getWifiNative().getUsableChannels(band,
587                                 OP_MODE_WIFI_AWARE,
588                                 WifiAvailableChannel.FILTER_NAN_INSTANT_MODE), null,
589                         TAG + "#get_instant_communication_channel");
590                 StringBuilder out = new StringBuilder();
591                 for (WifiAvailableChannel channel : channels) {
592                     out.append(channel.toString());
593                     out.append(", ");
594                 }
595                 pw_out.println(out.toString());
596                 return 0;
597             }
598             case "set_override_instant_communication_mode": {
599                 String arg = parentShell.getNextArgRequired();
600                 if (TextUtils.equals(arg, "2G")) {
601                     mOverrideInstantMode = INSTANT_MODE_24GHZ;
602                 } else if (TextUtils.equals(arg, "5G")) {
603                     mOverrideInstantMode = INSTANT_MODE_5GHZ;
604                 } else {
605                     pw_err.println("Unknown band -- " + arg);
606                     return -1;
607                 }
608                 return 0;
609             }
610             case "clear_override_instant_communication_mode": {
611                 mOverrideInstantMode = INSTANT_MODE_DISABLED;
612                 return 0;
613             }
614             case "set_cluster_id": {
615                 String arg = parentShell.getNextArgRequired();
616                 int clusterId;
617                 try {
618                     clusterId = Integer.valueOf(arg);
619                 } catch (NumberFormatException e) {
620                     pw_err.println("Can't convert value to integer -- '" + arg + "'");
621                     return -1;
622                 }
623 
624                 if (clusterId < ConfigRequest.CLUSTER_ID_MIN
625                         || clusterId > ConfigRequest.CLUSTER_ID_MAX) {
626                     pw_err.println("cluster ID must be in the range of 0x0000, 0xFFFF. "
627                             + "Cluster ID =" + arg);
628                     return -1;
629                 }
630 
631                 return setClusterId(clusterId) ? 0 : -1;
632             }
633             default:
634                 pw_err.println("Unknown 'wifiaware state_mgr <cmd>'");
635         }
636 
637         return -1;
638     }
639 
640     @Override
onReset()641     public void onReset() {
642         mSettableParameters.put(PARAM_ON_IDLE_DISABLE_AWARE, PARAM_ON_IDLE_DISABLE_AWARE_DEFAULT);
643         if (mDataPathMgr != null) {
644             mDataPathMgr.mAllowNdpResponderFromAnyOverride = false;
645         }
646     }
647 
648     @Override
onHelp(String command, BasicShellCommandHandler parentShell)649     public void onHelp(String command, BasicShellCommandHandler parentShell) {
650         final PrintWriter pw = parentShell.getOutPrintWriter();
651 
652         pw.println("  " + command);
653         pw.println("    set <name> <value>: sets named parameter to value. Names: "
654                 + mSettableParameters.keySet());
655         pw.println("    get <name>: gets named parameter value. Names: "
656                 + mSettableParameters.keySet());
657         pw.println("    get_capabilities: prints out the capabilities as a JSON string");
658         pw.println(
659                 "    allow_ndp_any true|false: configure whether Responders can be specified to "
660                         + "accept requests from ANY requestor (null peer spec)");
661         pw.println(" get_instant_communication_channel 2G|5G: get instant communication mode "
662                 + "channel available for the target band");
663         pw.println(" set_override_instant_communication_mode 2G|5G: override the instant "
664                 + "communication mode to 'enabled' with the specified band");
665         pw.println(" clear_override_instant_communication_mode: clear the override of the instant "
666                 + "communication mode");
667         pw.println(" set_cluster_id <value>: set the cluster id to request to join a cluster");
668     }
669 
670     /**
671      * Initialize the handler of the state manager with the specified thread
672      * looper.
673      *
674      * @param looper Thread looper on which to run the handler.
675      */
start(Context context, Looper looper, WifiAwareMetrics awareMetrics, WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, Clock clock, NetdWrapper netdWrapper, InterfaceConflictManager interfaceConflictMgr)676     public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
677             WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
678             Clock clock, NetdWrapper netdWrapper, InterfaceConflictManager interfaceConflictMgr) {
679         Log.i(TAG, "start()");
680 
681         mContext = context;
682         mAwareMetrics = awareMetrics;
683         mWifiPermissionsUtil = wifiPermissionsUtil;
684         mInterfaceConflictMgr = interfaceConflictMgr;
685         mSm = new WifiAwareStateMachine(TAG, looper);
686         mSm.setDbg(mVdbg);
687         mSm.start();
688         mHandler = new Handler(looper);
689 
690         mDataPathMgr = new WifiAwareDataPathStateManager(this, clock);
691         mDataPathMgr.start(mContext, mSm.getHandler().getLooper(), awareMetrics,
692                 wifiPermissionsUtil, permissionsWrapper, netdWrapper);
693 
694         mPowerManager = mContext.getSystemService(PowerManager.class);
695         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
696     }
697 
698     /**
699      * Initialize the late-initialization sub-services: depend on other services already existing.
700      */
startLate()701     public void startLate() {
702         delayedInitialization();
703         IntentFilter intentFilter = new IntentFilter();
704         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
705         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
706         intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
707         mContext.registerReceiver(
708                 new BroadcastReceiver() {
709                     @Override
710                     public void onReceive(Context context, Intent intent) {
711                         String action = intent.getAction();
712                         if (mVerboseLoggingEnabled) {
713                             Log.v(TAG, "BroadcastReceiver: action=" + action);
714                         }
715                         if (action.equals(Intent.ACTION_SCREEN_ON)
716                                 || action.equals(Intent.ACTION_SCREEN_OFF)) {
717                             reconfigure();
718                         }
719 
720                         if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {
721                             if (mSettableParameters.get(PARAM_ON_IDLE_DISABLE_AWARE) != 0) {
722                                 if (mPowerManager.isDeviceIdleMode()
723                                         && !isAnyCallerIgnoringBatteryOptimizations()) {
724                                     disableUsage(false);
725                                 } else {
726                                     enableUsage();
727                                 }
728                             } else {
729                                 reconfigure();
730                             }
731                         }
732                     }
733                 },
734                 intentFilter,
735                 null,
736                 mHandler);
737 
738         intentFilter = new IntentFilter();
739         intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
740         mContext.registerReceiver(
741                 new BroadcastReceiver() {
742                     @Override
743                     public void onReceive(Context context, Intent intent) {
744                         if (mVerboseLoggingEnabled) {
745                             Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent);
746                         }
747                         if (mWifiPermissionsUtil.isLocationModeEnabled()) {
748                             enableUsage();
749                         } else {
750                             if (SdkLevel.isAtLeastT()) {
751                                 handleLocationModeDisabled();
752                             } else {
753                                 disableUsage(false);
754                             }
755                         }
756                     }
757                 },
758                 intentFilter,
759                 null,
760                 mHandler);
761 
762         intentFilter = new IntentFilter();
763         intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
764         mContext.registerReceiver(
765                 new BroadcastReceiver() {
766                     @Override
767                     public void onReceive(Context context, Intent intent) {
768                         if (mVerboseLoggingEnabled) {
769                             Log.v(TAG, "onReceive: WIFI_STATE_CHANGED_ACTION: intent=" + intent);
770                         }
771                         boolean isEnabled =
772                                 intent.getIntExtra(
773                                         WifiManager.EXTRA_WIFI_STATE,
774                                         WifiManager.WIFI_STATE_UNKNOWN)
775                                         == WifiManager.WIFI_STATE_ENABLED;
776                         if (isEnabled) {
777                             enableUsage();
778                         } else {
779                             if (!isD2dAllowedWhenStaDisabled()) {
780                                 disableUsage(false);
781                             }
782                         }
783                     }
784                 },
785                 intentFilter,
786                 null,
787                 mHandler);
788         mSettingsConfigStore.registerChangeListener(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED,
789                 (key, value) -> {
790                     // Check setting & wifi enabled status only when feature is supported.
791                     if (mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()) {
792                         if (mSettingsConfigStore.get(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED)) {
793                             enableUsage();
794                         } else if (mWifiManager.getWifiState()
795                                 != WifiManager.WIFI_STATE_ENABLED) {
796                             disableUsage(false);
797                         }
798                     }
799                 }, mHandler);
800         if (isD2dAllowedWhenStaDisabled()) {
801             enableUsage();
802         }
803     }
804 
isD2dAllowedWhenStaDisabled()805     public boolean isD2dAllowedWhenStaDisabled() {
806         return mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()
807                 && mSettingsConfigStore.get(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED);
808     }
809 
810     private class CountryCodeChangeCallback implements
811             WifiManager.ActiveCountryCodeChangedCallback {
812 
813         @Override
onActiveCountryCodeChanged(@ndroidx.annotation.NonNull String countryCode)814         public void onActiveCountryCodeChanged(@androidx.annotation.NonNull String countryCode) {
815             mAwareBand5InstantCommunicationChannelFreq = -1;
816             reconfigure();
817         }
818 
819         @Override
onCountryCodeInactive()820         public void onCountryCodeInactive() {
821             // Ignore.
822         }
823     }
824 
825     /**
826      * Try to get capability if it is null.
827      */
tryToGetAwareCapability()828     public void tryToGetAwareCapability() {
829         if (mCapabilities != null) return;
830         // Internal request for fetching capabilities.
831         getAwareInterface(new WorkSource(Process.WIFI_UID));
832         queryCapabilities();
833         releaseAwareInterface();
834     }
835 
836     /**
837      * Get the client state for the specified ID (or null if none exists).
838      */
getClient(int clientId)839     /* package */ WifiAwareClientState getClient(int clientId) {
840         return mClients.get(clientId);
841     }
842 
843     /**
844      * Get the capabilities.
845      */
getCapabilities()846     public Capabilities getCapabilities() {
847         return mCapabilities;
848     }
849 
850     /**
851      * Get the available aware resources.
852      */
getAvailableAwareResources()853     public AwareResources getAvailableAwareResources() {
854         if (mCapabilities == null) {
855             if (mVerboseLoggingEnabled) {
856                 Log.v(TAG, "Aware capability hasn't loaded, resources is unknown.");
857             }
858             return null;
859         }
860         Pair<Integer, Integer> numOfDiscoverySessions = getNumOfDiscoverySessions();
861         int numOfAvailableNdps = mCapabilities.maxNdpSessions - mDataPathMgr.getNumOfNdps();
862         int numOfAvailablePublishSessions =
863                 mCapabilities.maxPublishes - numOfDiscoverySessions.first;
864         int numOfAvailableSubscribeSessions =
865                 mCapabilities.maxSubscribes - numOfDiscoverySessions.second;
866         if (numOfAvailableNdps < 0) {
867             Log.w(TAG, "Available NDPs number is negative, wrong capability?");
868         }
869         if (numOfAvailablePublishSessions < 0) {
870             Log.w(TAG, "Available publish session number is negative, wrong capability?");
871         }
872         if (numOfAvailableSubscribeSessions < 0) {
873             Log.w(TAG, "Available subscribe session number is negative, wrong capability?");
874         }
875         return new AwareResources(numOfAvailableNdps, numOfAvailablePublishSessions,
876                 numOfAvailableSubscribeSessions);
877     }
878 
getNumOfDiscoverySessions()879     private Pair<Integer, Integer> getNumOfDiscoverySessions() {
880         int numOfPub = 0;
881         int numOfSub = 0;
882         for (int i = 0; i < mClients.size(); i++) {
883             WifiAwareClientState clientState = mClients.valueAt(i);
884             for (int j = 0; j < clientState.getSessions().size(); j++) {
885                 WifiAwareDiscoverySessionState session = clientState.getSessions().valueAt(j);
886                 if (session.isPublishSession()) {
887                     numOfPub++;
888                 } else {
889                     numOfSub++;
890                 }
891             }
892         }
893         return Pair.create(numOfPub, numOfSub);
894     }
895 
896     /**
897      * Get the public characteristics derived from the capabilities. Use lazy initialization.
898      */
getCharacteristics()899     public Characteristics getCharacteristics() {
900         if (mCharacteristics == null && mCapabilities != null) {
901             mCharacteristics = mCapabilities.toPublicCharacteristics(
902                     mWifiInjector.getDeviceConfigFacade());
903         }
904 
905         return mCharacteristics;
906     }
907 
908     /**
909      * Check if there is any active attach session
910      */
isDeviceAttached()911     public boolean isDeviceAttached() {
912         return mClients != null && mClients.size() > 0;
913     }
914 
915     /*
916      * Cross-service API: synchronized but independent of state machine
917      */
918 
919     /**
920      * Translate (and return in the callback) the peerId to its MAC address representation.
921      */
requestMacAddresses(int uid, int[] peerIds, IWifiAwareMacAddressProvider callback)922     public void requestMacAddresses(int uid, int[] peerIds,
923             IWifiAwareMacAddressProvider callback) {
924         mSm.getHandler().post(() -> {
925             if (mVdbg) {
926                 Log.v(TAG, "requestMacAddresses: uid=" + uid + ", peerIds="
927                         + Arrays.toString(peerIds));
928             }
929             Map<Integer, MacAddrMapping> peerIdToMacMap = new HashMap<>();
930             for (int i = 0; i < mClients.size(); ++i) {
931                 WifiAwareClientState client = mClients.valueAt(i);
932                 if (client.getUid() != uid) {
933                     continue;
934                 }
935 
936                 SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions();
937                 for (int j = 0; j < sessions.size(); ++j) {
938                     WifiAwareDiscoverySessionState session = sessions.valueAt(j);
939 
940                     for (int peerId : peerIds) {
941                         WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo(
942                                 peerId);
943                         if (peerInfo != null) {
944                             MacAddrMapping mapping = new MacAddrMapping();
945                             mapping.peerId = peerId;
946                             mapping.macAddress = peerInfo.mMac;
947                             peerIdToMacMap.put(peerId, mapping);
948                         }
949                     }
950                 }
951             }
952 
953             try {
954                 MacAddrMapping[] peerIdToMacList = peerIdToMacMap.values()
955                         .toArray(new MacAddrMapping[0]);
956                 if (mVerboseLoggingEnabled) {
957                     Log.v(TAG, "requestMacAddresses: peerIdToMacList begin");
958                     for (MacAddrMapping mapping : peerIdToMacList) {
959                         Log.v(TAG, "    " + mapping.peerId + ": "
960                                 + MacAddress.fromBytes(mapping.macAddress));
961                     }
962                     Log.v(TAG, "requestMacAddresses: peerIdToMacList end");
963                 }
964                 callback.macAddress(peerIdToMacList);
965             } catch (RemoteException e) {
966                 Log.e(TAG, "requestMacAddress (sync): exception on callback -- " + e);
967             }
968         });
969     }
970 
971     /*
972      * COMMANDS
973      */
974 
975     /**
976      * Place a request for delayed start operation on the state machine queue.
977      */
delayedInitialization()978     public void delayedInitialization() {
979         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
980         msg.arg1 = COMMAND_TYPE_DELAYED_INITIALIZATION;
981         mSm.sendMessage(msg);
982     }
983 
984     /**
985      * Place a request to get the Wi-Fi Aware interface (before which no HAL command can be
986      * executed).
987      */
getAwareInterface(@onNull WorkSource requestorWs)988     public void getAwareInterface(@NonNull WorkSource requestorWs) {
989         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
990         msg.arg1 = COMMAND_TYPE_GET_AWARE;
991         msg.obj = requestorWs;
992         mSm.sendMessage(msg);
993     }
994 
995     /**
996      * Place a request to release the Wi-Fi Aware interface (after which no HAL command can be
997      * executed).
998      */
releaseAwareInterface()999     public void releaseAwareInterface() {
1000         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1001         msg.arg1 = COMMAND_TYPE_RELEASE_AWARE;
1002         mSm.sendMessage(msg);
1003     }
1004 
1005     /**
1006      * Enable instant communication mode if supported.
1007      * @param enabled true for enable, false for disable.
1008      */
enableInstantCommunicationMode(boolean enabled)1009     public void enableInstantCommunicationMode(boolean enabled) {
1010         if (mCapabilities == null) {
1011             if (mVerboseLoggingEnabled) {
1012                 Log.v(TAG, "Aware capability is not loaded.");
1013             }
1014             return;
1015         }
1016 
1017         if (!mCapabilities.isInstantCommunicationModeSupported) {
1018             if (mVerboseLoggingEnabled) {
1019                 Log.v(TAG, "Device does not support instant communication mode.");
1020             }
1021             return;
1022         }
1023         if (mInstantCommModeGlobalEnable == enabled) return;
1024 
1025         mInstantCommModeGlobalEnable = enabled;
1026         reconfigure();
1027     }
1028 
1029     /**
1030      * Set cluster ID if supported.
1031      * @param clusterId value ranges from 0x0000 to 0xFFFF.
1032      */
setClusterId(int clusterId)1033     private boolean setClusterId(int clusterId) {
1034         if (mCapabilities == null) {
1035             Log.e(TAG, "Aware capability is not loaded.");
1036             return false;
1037         }
1038 
1039         if (!mCapabilities.isSetClusterIdSupported) {
1040             Log.e(TAG, "Device does not support setting cluster ID.");
1041             return false;
1042         }
1043         if (mClusterIdInt == clusterId) return true;
1044 
1045         mClusterIdInt = clusterId;
1046         reconfigure();
1047         return true;
1048     }
1049 
1050     /**
1051      * Get if instant communication mode is currently enabled.
1052      * @return true if enabled, false otherwise.
1053      */
isInstantCommModeGlobalEnable()1054     public boolean isInstantCommModeGlobalEnable() {
1055         return mInstantCommModeGlobalEnable;
1056     }
1057 
1058     /**
1059      * Get if set channel on data-path request is supported.
1060      * @return true if supported, false otherwise.
1061      */
isSetChannelOnDataPathSupported()1062     public boolean isSetChannelOnDataPathSupported() {
1063         return mContext.getResources()
1064                 .getBoolean(R.bool.config_wifiSupportChannelOnDataPath);
1065     }
1066 
1067     /**
1068      * Accept using parameter from external to config the Aware,
1069      * @see WifiAwareManager#setAwareParams(AwareParams)
1070      */
setAwareParams(AwareParams parameters)1071     public void setAwareParams(AwareParams parameters) {
1072         mHandler.post(() -> {
1073             mWifiAwareNativeApi.setAwareParams(parameters);
1074             reconfigure();
1075         });
1076     }
1077 
1078     /**
1079      * @see WifiAwareManager#resetPairedDevices()
1080      */
resetPairedDevices(String callingPackage)1081     public void resetPairedDevices(String callingPackage) {
1082         mHandler.post(() -> mPairingConfigManager.removePackage(callingPackage));
1083     }
1084 
1085     /**
1086      * @see WifiAwareManager#removePairedDevice(String)
1087      */
removePairedDevice(String callingPackage, String alias)1088     public void removePairedDevice(String callingPackage, String alias) {
1089         mHandler.post(
1090                 () -> mPairingConfigManager.removePairedDevice(callingPackage, alias));
1091     }
1092 
1093     /**
1094      * @see WifiAwareManager#getPairedDevices(Executor, Consumer)
1095      */
getPairedDevices(String callingPackage, IListListener listener)1096     public void getPairedDevices(String callingPackage, IListListener listener) {
1097         mHandler.post(() -> {
1098                     try {
1099                         listener.onResult(mPairingConfigManager
1100                                 .getAllPairedDevices(callingPackage));
1101                     } catch (RemoteException e) {
1102                         Log.e(TAG, e.getMessage(), e);
1103                     }
1104                 }
1105         );
1106     }
1107 
1108     /**
1109      * @see android.net.wifi.aware.WifiAwareSession#setMasterPreference(int)
1110      */
setMasterPreference(int clientId, int masterPreference)1111     public void setMasterPreference(int clientId, int masterPreference) {
1112         mHandler.post(() -> {
1113             WifiAwareClientState state = mClients.get(clientId);
1114             if (state == null) {
1115                 Log.e(TAG, "client state is missing");
1116                 return;
1117             }
1118             state.getConfigRequest().mMasterPreference = masterPreference;
1119             reconfigure();
1120         });
1121     }
1122 
1123     /**
1124      * @see android.net.wifi.aware.WifiAwareSession#getMasterPreference(Executor, Consumer)
1125      */
getMasterPreference(int clientId, IIntegerListener listener)1126     public void getMasterPreference(int clientId, IIntegerListener listener) {
1127         mHandler.post(() -> {
1128             WifiAwareClientState state = mClients.get(clientId);
1129             if (state == null) {
1130                 Log.e(TAG, "client state is missing");
1131                 return;
1132             }
1133             try {
1134                 listener.onResult(state.getConfigRequest().mMasterPreference);
1135             } catch (RemoteException e) {
1136                 Log.e(TAG, e.getMessage(), e);
1137             }
1138         });
1139     }
1140 
1141     /**
1142      * @see WifiAwareManager#setOpportunisticModeEnabled(boolean)
1143      */
setOpportunisticPackage(String ctxPkg, boolean enabled)1144     public void setOpportunisticPackage(String ctxPkg, boolean enabled) {
1145         mHandler.post(() -> {
1146             if (enabled) {
1147                 mOpportunisticSet.add(ctxPkg);
1148             } else {
1149                 mOpportunisticSet.remove(ctxPkg);
1150             }
1151             if (mClients.size() == 0) {
1152                 return;
1153             }
1154             if (!mWifiAwareNativeManager.replaceRequestorWs(createMergedRequestorWs())) {
1155                 Log.w(TAG, "Failed to replace requestorWs");
1156             }
1157         });
1158     }
1159 
1160     /**
1161      * @see WifiAwareManager#isOpportunisticModeEnabled(Executor, Consumer)
1162      */
isOpportunistic(String ctxPkg, IBooleanListener listener)1163     public void isOpportunistic(String ctxPkg, IBooleanListener listener) {
1164         mHandler.post(() -> {
1165             try {
1166                 listener.onResult(mOpportunisticSet.contains(ctxPkg));
1167             } catch (RemoteException e) {
1168                 Log.e(TAG, e.getMessage(), e);
1169             }
1170         });
1171     }
1172 
1173     /**
1174      * Place a request for a new client connection on the state machine queue.
1175      */
connect(int clientId, int uid, int pid, String callingPackage, @Nullable String callingFeatureId, IWifiAwareEventCallback callback, ConfigRequest configRequest, boolean notifyOnIdentityChanged, Bundle extra, boolean forAwareOffload)1176     public void connect(int clientId, int uid, int pid, String callingPackage,
1177             @Nullable String callingFeatureId, IWifiAwareEventCallback callback,
1178             ConfigRequest configRequest, boolean notifyOnIdentityChanged, Bundle extra,
1179             boolean forAwareOffload) {
1180         boolean reEnableAware = false;
1181         // If FW could not handle the Aware request priority, disable the Aware first
1182         if (!mContext.getResources()
1183                 .getBoolean(R.bool.config_wifiAwareOffloadingFirmwareHandlePriority)
1184                 && isAwareOffloading() && !forAwareOffload) {
1185             // Do not release Aware, as new request will get Interface again
1186             deferDisableAware(false);
1187             reEnableAware = true;
1188         }
1189         int callerType;
1190         if (SdkLevel.isAtLeastS()) {
1191             AttributionSource attributionSource =
1192                     extra.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE);
1193             callerType = mWifiPermissionsUtil.getWifiCallerType(attributionSource);
1194         } else {
1195             callerType = mWifiPermissionsUtil.getWifiCallerType(uid, callingPackage);
1196         }
1197         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1198         msg.arg1 = COMMAND_TYPE_CONNECT;
1199         msg.arg2 = clientId;
1200         Pair<IWifiAwareEventCallback, Object> callbackAndAttributionSource = new Pair<>(
1201                 callback, extra.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
1202         msg.obj = callbackAndAttributionSource;
1203         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, configRequest);
1204         msg.getData().putInt(MESSAGE_BUNDLE_KEY_UID, uid);
1205         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PID, pid);
1206         msg.getData().putString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE, callingPackage);
1207         msg.getData().putString(MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID, callingFeatureId);
1208         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE,
1209                 notifyOnIdentityChanged);
1210         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_AWARE_OFFLOAD, forAwareOffload);
1211         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_RE_ENABLE_AWARE_FROM_OFFLOAD, reEnableAware);
1212         msg.getData().putInt(MESSAGE_BUNDLE_KEY_CALLER_TYPE, callerType);
1213         mSm.sendMessage(msg);
1214         // Clean the client after the connect to avoid Aware disable
1215         if (!forAwareOffload) {
1216             for (int i = 0; i < mClients.size(); i++) {
1217                 WifiAwareClientState clientState = mClients.valueAt(i);
1218                 if (clientState.isAwareOffload()) {
1219                     disconnect(clientState.getClientId());
1220                 }
1221             }
1222         }
1223     }
1224 
1225     /**
1226      * Place a request to disconnect (destroy) an existing client on the state
1227      * machine queue.
1228      */
disconnect(int clientId)1229     public void disconnect(int clientId) {
1230         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1231         msg.arg1 = COMMAND_TYPE_DISCONNECT;
1232         msg.arg2 = clientId;
1233         mSm.sendMessage(msg);
1234     }
1235 
1236     /**
1237      * Place a request to defer Disable Aware on the state machine queue.
1238      * @param releaseAware
1239      */
deferDisableAware(boolean releaseAware)1240     private void deferDisableAware(boolean releaseAware) {
1241         mAwareIsDisabling = true;
1242         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1243         msg.arg1 = COMMAND_TYPE_DISABLE;
1244         msg.obj = releaseAware;
1245         mSm.sendMessage(msg);
1246     }
1247 
1248     /**
1249      * Place a request to reconfigure Aware. No additional input - intended to use current
1250      * power settings when executed. Thus possibly entering or exiting power saving mode if
1251      * needed (or do nothing if Aware is not active).
1252      */
reconfigure()1253     public void reconfigure() {
1254         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1255         msg.arg1 = COMMAND_TYPE_RECONFIGURE;
1256         mSm.sendMessage(msg);
1257     }
1258 
1259     /**
1260      * Place a request to stop a discovery session on the state machine queue.
1261      */
terminateSession(int clientId, int sessionId)1262     public void terminateSession(int clientId, int sessionId) {
1263         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1264         msg.arg1 = COMMAND_TYPE_TERMINATE_SESSION;
1265         msg.arg2 = clientId;
1266         msg.obj = sessionId;
1267         mSm.sendMessage(msg);
1268     }
1269 
1270     /**
1271      * Place a request to start a new publish discovery session on the state
1272      * machine queue.
1273      */
publish(int clientId, PublishConfig publishConfig, IWifiAwareDiscoverySessionCallback callback)1274     public void publish(int clientId, PublishConfig publishConfig,
1275             IWifiAwareDiscoverySessionCallback callback) {
1276         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1277         msg.arg1 = COMMAND_TYPE_PUBLISH;
1278         msg.arg2 = clientId;
1279         msg.obj = callback;
1280         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, publishConfig);
1281         mSm.sendMessage(msg);
1282     }
1283 
1284     /**
1285      * Place a request to modify an existing publish discovery session on the
1286      * state machine queue.
1287      */
updatePublish(int clientId, int sessionId, PublishConfig publishConfig)1288     public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) {
1289         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1290         msg.arg1 = COMMAND_TYPE_UPDATE_PUBLISH;
1291         msg.arg2 = clientId;
1292         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, publishConfig);
1293         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1294         mSm.sendMessage(msg);
1295     }
1296 
1297     /**
1298      * Place a request to start a new subscribe discovery session on the state
1299      * machine queue.
1300      */
subscribe(int clientId, SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback)1301     public void subscribe(int clientId, SubscribeConfig subscribeConfig,
1302             IWifiAwareDiscoverySessionCallback callback) {
1303         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1304         msg.arg1 = COMMAND_TYPE_SUBSCRIBE;
1305         msg.arg2 = clientId;
1306         msg.obj = callback;
1307         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, subscribeConfig);
1308         mSm.sendMessage(msg);
1309     }
1310 
1311     /**
1312      * Place a request to modify an existing subscribe discovery session on the
1313      * state machine queue.
1314      */
updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig)1315     public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) {
1316         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1317         msg.arg1 = COMMAND_TYPE_UPDATE_SUBSCRIBE;
1318         msg.arg2 = clientId;
1319         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, subscribeConfig);
1320         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1321         mSm.sendMessage(msg);
1322     }
1323 
1324     /**
1325      * Place a request to send a message on a discovery session on the state
1326      * machine queue.
1327      */
sendMessage(int uid, int clientId, int sessionId, int peerId, byte[] message, int messageId, int retryCount)1328     public void sendMessage(int uid, int clientId, int sessionId, int peerId, byte[] message,
1329             int messageId, int retryCount) {
1330         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1331         msg.arg1 = COMMAND_TYPE_ENQUEUE_SEND_MESSAGE;
1332         msg.arg2 = clientId;
1333         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1334         msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID, peerId);
1335         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message);
1336         msg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID, messageId);
1337         msg.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT, retryCount);
1338         msg.getData().putInt(MESSAGE_BUNDLE_KEY_UID, uid);
1339         mSm.sendMessage(msg);
1340     }
1341 
1342     /**
1343      * Initiate a NAN pairing setup request
1344      */
initiateNanPairingSetupRequest(int clientId, int sessionId, int peerId, String password, String pairingDeviceAlias, int cipherSuite)1345     public void initiateNanPairingSetupRequest(int clientId, int sessionId, int peerId,
1346             String password, String pairingDeviceAlias, int cipherSuite) {
1347         initiateNanPairingRequest(clientId, sessionId, peerId, password, pairingDeviceAlias,
1348                 NAN_PAIRING_REQUEST_TYPE_SETUP, null,
1349                 TextUtils.isEmpty(password) ? NAN_PAIRING_AKM_PASN : NAN_PAIRING_AKM_SAE,
1350                 cipherSuite);
1351     }
1352 
initiateNanPairingVerificationRequest(int clientId, int sessionId, int peerId, String pairingDeviceAlias, byte[] pmk, int akm, int cipherSuite)1353     private void initiateNanPairingVerificationRequest(int clientId, int sessionId, int peerId,
1354             String pairingDeviceAlias, byte[] pmk, int akm, int cipherSuite) {
1355         initiateNanPairingRequest(clientId, sessionId, peerId, null, pairingDeviceAlias,
1356                 NAN_PAIRING_REQUEST_TYPE_VERIFICATION, pmk, akm, cipherSuite);
1357     }
1358 
initiateNanPairingRequest(int clientId, int sessionId, int peerId, String password, String pairingDeviceAlias, int requestType, byte[] pmk, int akm, int cipherSuite)1359     private void initiateNanPairingRequest(int clientId, int sessionId, int peerId,
1360             String password, String pairingDeviceAlias, int requestType, byte[] pmk, int akm,
1361             int cipherSuite) {
1362         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1363         msg.arg1 = COMMAND_TYPE_INITIATE_PAIRING_REQUEST;
1364         msg.arg2 = clientId;
1365         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1366         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
1367         msg.getData().putString(MESSAGE_BUNDLE_KEY_PAIRING_ALIAS, pairingDeviceAlias);
1368         msg.getData().putString(MESSAGE_BUNDLE_KEY_PAIRING_PASSWORD, password);
1369         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE, requestType);
1370         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_AKM, akm);
1371         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_CIPHER_SUITE, cipherSuite);
1372         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PAIRING_PMK, pmk);
1373         mSm.sendMessage(msg);
1374     }
1375 
1376     /**
1377      * Response to a NAN pairing setup request
1378      */
responseNanPairingSetupRequest(int clientId, int sessionId, int peerId, int requestId, String password, String pairingDeviceAlias, boolean accept, int cipherSuite)1379     public void responseNanPairingSetupRequest(int clientId, int sessionId, int peerId,
1380             int requestId, String password, String pairingDeviceAlias, boolean accept,
1381             int cipherSuite) {
1382         responseNanPairingRequest(clientId, sessionId, peerId, requestId, password,
1383                 pairingDeviceAlias, NAN_PAIRING_REQUEST_TYPE_SETUP, null,
1384                 TextUtils.isEmpty(password) ? NAN_PAIRING_AKM_PASN : NAN_PAIRING_AKM_SAE, accept,
1385                 cipherSuite);
1386     }
1387 
responseNanPairingVerificationRequest(int clientId, int sessionId, int peerId, int requestId, String pairingDeviceAlias, boolean accept, byte[] pmk, int akm, int cipherSuite)1388     private void responseNanPairingVerificationRequest(int clientId, int sessionId, int peerId,
1389             int requestId, String pairingDeviceAlias, boolean accept, byte[] pmk, int akm,
1390             int cipherSuite) {
1391         responseNanPairingRequest(clientId, sessionId, peerId, requestId, null,
1392                 pairingDeviceAlias, NAN_PAIRING_REQUEST_TYPE_VERIFICATION, pmk, akm, accept,
1393                 cipherSuite);
1394     }
1395 
responseNanPairingRequest(int clientId, int sessionId, int peerId, int requestId, String password, String pairingDeviceAlias, int requestType, byte[] pmk, int akm, boolean accept, int cipherSuite)1396     private void responseNanPairingRequest(int clientId, int sessionId, int peerId, int requestId,
1397             String password, String pairingDeviceAlias, int requestType, byte[] pmk, int akm,
1398             boolean accept, int cipherSuite) {
1399         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1400         msg.arg1 = COMMAND_TYPE_RESPONSE_PAIRING_REQUEST;
1401         msg.arg2 = clientId;
1402         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1403         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
1404         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID, requestId);
1405         msg.getData().putString(MESSAGE_BUNDLE_KEY_PAIRING_ALIAS, pairingDeviceAlias);
1406         msg.getData().putString(MESSAGE_BUNDLE_KEY_PAIRING_PASSWORD, password);
1407         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE, requestType);
1408         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_AKM, akm);
1409         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_CIPHER_SUITE, cipherSuite);
1410         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_PAIRING_PMK, pmk);
1411         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_PAIRING_ACCEPT, accept);
1412         mSm.sendMessage(msg);
1413     }
1414 
1415     /**
1416      * Initiate a bootstrapping request
1417      */
initiateBootStrappingSetupRequest(int clientId, int sessionId, int peerId, int method, long comeBackDelayMills, byte[] cookie)1418     public void initiateBootStrappingSetupRequest(int clientId, int sessionId, int peerId, int
1419             method, long comeBackDelayMills, byte[] cookie) {
1420         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1421         msg.arg1 = COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST;
1422         msg.arg2 = clientId;
1423         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1424         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
1425         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD, method);
1426         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_COOKIE, cookie);
1427         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_IS_COME_BACK_REQUEST,
1428                 comeBackDelayMills > 0);
1429         mSm.sendMessageDelayed(msg, comeBackDelayMills);
1430     }
1431 
1432     /**
1433      * Respond to a bootstrapping request
1434      */
respondToBootstrappingRequest(int clientId, int sessionId, int peerId, int bootstrappingId, boolean accept, int method)1435     private void respondToBootstrappingRequest(int clientId, int sessionId, int peerId,
1436             int bootstrappingId, boolean accept, int method) {
1437         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1438         msg.arg1 = COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST;
1439         msg.arg2 = clientId;
1440         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1441         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
1442         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_ACCEPT, accept);
1443         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD, method);
1444         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID, bootstrappingId);
1445         mSm.sendMessage(msg);
1446     }
1447 
1448     /**
1449      * Enable usage of Aware. Doesn't actually turn on Aware (form clusters) - that
1450      * only happens when a connection is created.
1451      */
enableUsage()1452     public void enableUsage() {
1453         if (mSettableParameters.get(PARAM_ON_IDLE_DISABLE_AWARE) != 0
1454                 && mPowerManager.isDeviceIdleMode()) {
1455             if (mVerboseLoggingEnabled) {
1456                 Log.d(TAG, "enableUsage(): while device is in IDLE mode - ignoring");
1457             }
1458             return;
1459         }
1460         if (!SdkLevel.isAtLeastT() && !mWifiPermissionsUtil.isLocationModeEnabled()) {
1461             if (mVerboseLoggingEnabled) {
1462                 Log.d(TAG, "enableUsage(): while location is disabled - ignoring");
1463             }
1464             return;
1465         }
1466         if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) {
1467             if (!isD2dAllowedWhenStaDisabled()) {
1468                 if (mVerboseLoggingEnabled) {
1469                     Log.d(TAG, "enableUsage(): while Wi-Fi is disabled"
1470                             + " & D2D isn't allowed - ignoring");
1471                 }
1472                 return;
1473             }
1474         }
1475         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1476         msg.arg1 = COMMAND_TYPE_ENABLE_USAGE;
1477         mSm.sendMessage(msg);
1478     }
1479 
1480     /**
1481      * Disable usage of Aware. Terminates all existing clients with onAwareDown().
1482      * @param markAsAvailable mark the Aware service as available to all app or not.
1483      */
disableUsage(boolean markAsAvailable)1484     public void disableUsage(boolean markAsAvailable) {
1485         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1486         msg.arg1 = COMMAND_TYPE_DISABLE_USAGE;
1487         msg.arg2 = markAsAvailable ? 1 : 0;
1488         mSm.sendMessage(msg);
1489     }
1490 
1491     /**
1492      * Checks whether Aware usage is enabled (not necessarily that Aware is up right
1493      * now) or disabled.
1494      *
1495      * @return A boolean indicating whether Aware usage is enabled (true) or
1496      *         disabled (false).
1497      */
isUsageEnabled()1498     public boolean isUsageEnabled() {
1499         return mUsageEnabled;
1500     }
1501 
1502     /**
1503      * Get the capabilities of the current Aware firmware.
1504      */
queryCapabilities()1505     public void queryCapabilities() {
1506         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1507         msg.arg1 = COMMAND_TYPE_GET_CAPABILITIES;
1508         mSm.sendMessage(msg);
1509     }
1510 
1511     /**
1512      * delete all Aware data path interfaces.
1513      */
deleteAllDataPathInterfaces()1514     public void deleteAllDataPathInterfaces() {
1515         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1516         msg.arg1 = COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES;
1517         mSm.sendMessage(msg);
1518     }
1519 
1520     /**
1521      * Create the specified data-path interface. Doesn't actually creates a data-path.
1522      */
createDataPathInterface(String interfaceName)1523     public void createDataPathInterface(String interfaceName) {
1524         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1525         msg.arg1 = COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE;
1526         msg.obj = interfaceName;
1527         mSm.sendMessage(msg);
1528     }
1529 
1530     /**
1531      * Deletes the specified data-path interface.
1532      */
deleteDataPathInterface(String interfaceName)1533     public void deleteDataPathInterface(String interfaceName) {
1534         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1535         msg.arg1 = COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE;
1536         msg.obj = interfaceName;
1537         mSm.sendMessage(msg);
1538     }
1539 
1540     /**
1541      * Command to initiate a data-path (executed by the initiator).
1542      */
initiateDataPathSetup(WifiAwareNetworkSpecifier networkSpecifier, int peerId, int channelRequestType, int channel, byte[] peer, String interfaceName, boolean isOutOfBand, byte[] appInfo)1543     public void initiateDataPathSetup(WifiAwareNetworkSpecifier networkSpecifier, int peerId,
1544             int channelRequestType, int channel, byte[] peer, String interfaceName,
1545             boolean isOutOfBand, byte[] appInfo) {
1546         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1547         msg.arg1 = COMMAND_TYPE_INITIATE_DATA_PATH_SETUP;
1548         msg.obj = networkSpecifier;
1549         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
1550         msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE, channelRequestType);
1551         msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL, channel);
1552         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peer);
1553         msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName);
1554         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_OOB, isOutOfBand);
1555         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_APP_INFO, appInfo);
1556         mSm.sendMessage(msg);
1557     }
1558 
1559     /**
1560      * Command to respond to the data-path request (executed by the responder).
1561      */
respondToDataPathRequest(boolean accept, int ndpId, String interfaceName, byte[] appInfo, boolean isOutOfBand, WifiAwareNetworkSpecifier networkSpecifier)1562     public void respondToDataPathRequest(boolean accept, int ndpId, String interfaceName,
1563             byte[] appInfo, boolean isOutOfBand,
1564             WifiAwareNetworkSpecifier networkSpecifier) {
1565         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1566         msg.arg1 = COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST;
1567         msg.arg2 = ndpId;
1568         msg.obj = networkSpecifier;
1569         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_ACCEPT_STATE, accept);
1570         msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName);
1571         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_APP_INFO, appInfo);
1572         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_OOB, isOutOfBand);
1573         mSm.sendMessage(msg);
1574     }
1575 
1576     /**
1577      * Command to terminate the specified data-path.
1578      */
endDataPath(int ndpId)1579     public void endDataPath(int ndpId) {
1580         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1581         msg.arg1 = COMMAND_TYPE_END_DATA_PATH;
1582         msg.arg2 = ndpId;
1583         mSm.sendMessage(msg);
1584     }
1585 
1586     /**
1587      * Command to terminate the specified data-path.
1588      */
endPairing(int pairingId)1589     public void endPairing(int pairingId) {
1590         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1591         msg.arg1 = COMMAND_TYPE_END_PAIRING;
1592         msg.arg2 = pairingId;
1593         mSm.sendMessage(msg);
1594     }
1595 
1596     /**
1597      * Suspend the specified Aware session.
1598      */
suspend(int clientId, int sessionId)1599     public void suspend(int clientId, int sessionId) {
1600         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1601         msg.arg1 = COMMAND_TYPE_SUSPEND_SESSION;
1602         msg.arg2 = clientId;
1603         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1604         mSm.sendMessage(msg);
1605     }
1606 
1607     /**
1608      * Resume the specified (suspended) Aware session.
1609      */
resume(int clientId, int sessionId)1610     public void resume(int clientId, int sessionId) {
1611         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1612         msg.arg1 = COMMAND_TYPE_RESUME_SESSION;
1613         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
1614         msg.arg2 = clientId;
1615         mSm.sendMessage(msg);
1616     }
1617 
1618     /**
1619      * Aware follow-on messages (L2 messages) are queued by the firmware for transmission
1620      * on-the-air. The firmware has limited queue depth. The host queues all messages and doles
1621      * them out to the firmware when possible. This command removes the next messages for
1622      * transmission from the host queue and attempts to send it through the firmware. The queues
1623      * are inspected when the command is executed - not when the command is placed on the handler
1624      * (i.e. not evaluated here).
1625      */
transmitNextMessage()1626     private void transmitNextMessage() {
1627         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
1628         msg.arg1 = COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE;
1629         mSm.sendMessage(msg);
1630     }
1631 
1632     /*
1633      * RESPONSES
1634      */
1635 
1636     /**
1637      * Place a callback request on the state machine queue: configuration
1638      * request completed (successfully).
1639      */
onConfigSuccessResponse(short transactionId)1640     public void onConfigSuccessResponse(short transactionId) {
1641         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1642         msg.arg1 = RESPONSE_TYPE_ON_CONFIG_SUCCESS;
1643         msg.arg2 = transactionId;
1644         mSm.sendMessage(msg);
1645     }
1646 
1647     /**
1648      * Place a callback request on the state machine queue: configuration
1649      * request failed.
1650      */
onConfigFailedResponse(short transactionId, int reason)1651     public void onConfigFailedResponse(short transactionId, int reason) {
1652         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1653         msg.arg1 = RESPONSE_TYPE_ON_CONFIG_FAIL;
1654         msg.arg2 = transactionId;
1655         msg.obj = reason;
1656         mSm.sendMessage(msg);
1657     }
1658 
1659     /**
1660      * Place a callback request on the stage machine queue: disable request finished
1661      * (with the provided reason code).
1662      */
onDisableResponse(short transactionId, int reason)1663     public void onDisableResponse(short transactionId, int reason) {
1664         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1665         msg.arg1 = RESPONSE_TYPE_ON_DISABLE;
1666         msg.arg2 = transactionId;
1667         msg.obj = reason;
1668         mSm.sendMessage(msg);
1669     }
1670 
1671     /**
1672      * Place a callback request on the state machine queue: session
1673      * configuration (new or update) request succeeded.
1674      */
onSessionConfigSuccessResponse(short transactionId, boolean isPublish, byte pubSubId)1675     public void onSessionConfigSuccessResponse(short transactionId, boolean isPublish,
1676             byte pubSubId) {
1677         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1678         msg.arg1 = RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS;
1679         msg.arg2 = transactionId;
1680         msg.obj = pubSubId;
1681         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish);
1682         mSm.sendMessage(msg);
1683     }
1684 
1685     /**
1686      * Place a callback request on the state machine queue: session
1687      * configuration (new or update) request failed.
1688      */
onSessionConfigFailResponse(short transactionId, boolean isPublish, int reason)1689     public void onSessionConfigFailResponse(short transactionId, boolean isPublish, int reason) {
1690         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1691         msg.arg1 = RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL;
1692         msg.arg2 = transactionId;
1693         msg.obj = reason;
1694         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish);
1695         mSm.sendMessage(msg);
1696     }
1697 
1698     /**
1699      * Place a callback request on the state machine queue: message has been queued successfully.
1700      */
onMessageSendQueuedSuccessResponse(short transactionId)1701     public void onMessageSendQueuedSuccessResponse(short transactionId) {
1702         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1703         msg.arg1 = RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS;
1704         msg.arg2 = transactionId;
1705         mSm.sendMessage(msg);
1706     }
1707 
1708     /**
1709      * Place a callback request on the state machine queue: attempt to queue the message failed.
1710      */
onMessageSendQueuedFailResponse(short transactionId, int reason)1711     public void onMessageSendQueuedFailResponse(short transactionId, int reason) {
1712         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1713         msg.arg1 = RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL;
1714         msg.arg2 = transactionId;
1715         msg.obj = reason;
1716         mSm.sendMessage(msg);
1717     }
1718 
1719     /**
1720      * Place a callback request on the state machine queue: update vendor
1721      * capabilities of the Aware stack.
1722      */
onCapabilitiesUpdateResponse(short transactionId, Capabilities capabilities)1723     public void onCapabilitiesUpdateResponse(short transactionId,
1724             Capabilities capabilities) {
1725         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1726         msg.arg1 = RESPONSE_TYPE_ON_CAPABILITIES_UPDATED;
1727         msg.arg2 = transactionId;
1728         msg.obj = capabilities;
1729         mSm.sendMessage(msg);
1730     }
1731 
1732     /**
1733      * Places a callback request on the state machine queue: data-path interface creation command
1734      * completed.
1735      */
onCreateDataPathInterfaceResponse(short transactionId, boolean success, int reasonOnFailure)1736     public void onCreateDataPathInterfaceResponse(short transactionId, boolean success,
1737             int reasonOnFailure) {
1738         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1739         msg.arg1 = RESPONSE_TYPE_ON_CREATE_INTERFACE;
1740         msg.arg2 = transactionId;
1741         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success);
1742         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure);
1743         mSm.sendMessage(msg);
1744     }
1745 
1746     /**
1747      * Places a callback request on the state machine queue: data-path interface deletion command
1748      * completed.
1749      */
onDeleteDataPathInterfaceResponse(short transactionId, boolean success, int reasonOnFailure)1750     public void onDeleteDataPathInterfaceResponse(short transactionId, boolean success,
1751             int reasonOnFailure) {
1752         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1753         msg.arg1 = RESPONSE_TYPE_ON_DELETE_INTERFACE;
1754         msg.arg2 = transactionId;
1755         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success);
1756         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure);
1757         mSm.sendMessage(msg);
1758     }
1759 
1760     /**
1761      * Response from firmware to initiateDataPathSetup(...). Indicates that command has started
1762      * succesfully (not completed!).
1763      */
onInitiateDataPathResponseSuccess(short transactionId, int ndpId)1764     public void onInitiateDataPathResponseSuccess(short transactionId, int ndpId) {
1765         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1766         msg.arg1 = RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS;
1767         msg.arg2 = transactionId;
1768         msg.obj = ndpId;
1769         mSm.sendMessage(msg);
1770     }
1771 
1772     /**
1773      * Response from firmware to initiateDataPathSetup(...).
1774      * Indicates that command has failed.
1775      */
onInitiateDataPathResponseFail(short transactionId, int reason)1776     public void onInitiateDataPathResponseFail(short transactionId, int reason) {
1777         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1778         msg.arg1 = RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL;
1779         msg.arg2 = transactionId;
1780         msg.obj = reason;
1781         mSm.sendMessage(msg);
1782     }
1783 
1784     /**
1785      * Response from firmware to initiatePairing(...). Indicates that command has started
1786      * successfully (not completed!).
1787      */
onInitiatePairingResponseSuccess(short transactionId, int pairId)1788     public void onInitiatePairingResponseSuccess(short transactionId, int pairId) {
1789         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1790         msg.arg1 = RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS;
1791         msg.arg2 = transactionId;
1792         msg.obj = pairId;
1793         mSm.sendMessage(msg);
1794     }
1795 
1796     /**
1797      * Response from firmware to initiatePairing(...).
1798      * Indicates that command has failed.
1799      */
onInitiatePairingResponseFail(short transactionId, int reason)1800     public void onInitiatePairingResponseFail(short transactionId, int reason) {
1801         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1802         msg.arg1 = RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL;
1803         msg.arg2 = transactionId;
1804         msg.obj = reason;
1805         mSm.sendMessage(msg);
1806     }
1807 
1808     /**
1809      * Response from firmware to respondToPairingRequest(...). Indicates that command has started
1810      * successfully (not completed!).
1811      */
onRespondToPairingIndicationResponseSuccess(short transactionId)1812     public void onRespondToPairingIndicationResponseSuccess(short transactionId) {
1813         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1814         msg.arg1 = RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS;
1815         msg.arg2 = transactionId;
1816         mSm.sendMessage(msg);
1817     }
1818 
1819     /**
1820      * Response from firmware to respondToPairingRequest(...).
1821      * Indicates that command has failed.
1822      */
onRespondToPairingIndicationResponseFail(short transactionId, int reason)1823     public void onRespondToPairingIndicationResponseFail(short transactionId, int reason) {
1824         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1825         msg.arg1 = RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL;
1826         msg.arg2 = transactionId;
1827         msg.obj = reason;
1828         mSm.sendMessage(msg);
1829     }
1830 
1831     /**
1832      * Response from firmware to initiateDataPathSetup(...). Indicates that command has started
1833      * successfully (not completed!).
1834      */
onInitiateBootStrappingResponseSuccess(short transactionId, int ndpId)1835     public void onInitiateBootStrappingResponseSuccess(short transactionId, int ndpId) {
1836         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1837         msg.arg1 = RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS;
1838         msg.arg2 = transactionId;
1839         msg.obj = ndpId;
1840         mSm.sendMessage(msg);
1841     }
1842 
1843     /**
1844      * Response from firmware to initiateDataPathSetup(...).
1845      * Indicates that command has failed.
1846      */
onInitiateBootStrappingResponseFail(short transactionId, int reason)1847     public void onInitiateBootStrappingResponseFail(short transactionId, int reason) {
1848         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1849         msg.arg1 = RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL;
1850         msg.arg2 = transactionId;
1851         msg.obj = reason;
1852         mSm.sendMessage(msg);
1853     }
1854 
1855     /**
1856      * Response from firmware to initiateDataPathSetup(...). Indicates that command has started
1857      * successfully (not completed!).
1858      */
onRespondToBootstrappingIndicationResponseSuccess(short transactionId)1859     public void onRespondToBootstrappingIndicationResponseSuccess(short transactionId) {
1860         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1861         msg.arg1 = RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS;
1862         msg.arg2 = transactionId;
1863         mSm.sendMessage(msg);
1864     }
1865 
1866     /**
1867      * Response from firmware to initiateDataPathSetup(...).
1868      * Indicates that command has failed.
1869      */
onRespondToBootstrappingIndicationResponseFail(short transactionId, int reason)1870     public void onRespondToBootstrappingIndicationResponseFail(short transactionId, int reason) {
1871         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1872         msg.arg1 = RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL;
1873         msg.arg2 = transactionId;
1874         msg.obj = reason;
1875         mSm.sendMessage(msg);
1876     }
1877 
1878     /**
1879      * Response from firmware to
1880      * {@link #respondToDataPathRequest(boolean, int, String, byte[], boolean, WifiAwareNetworkSpecifier)}
1881      */
onRespondToDataPathSetupRequestResponse(short transactionId, boolean success, int reasonOnFailure)1882     public void onRespondToDataPathSetupRequestResponse(short transactionId, boolean success,
1883             int reasonOnFailure) {
1884         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1885         msg.arg1 = RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST;
1886         msg.arg2 = transactionId;
1887         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success);
1888         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure);
1889         mSm.sendMessage(msg);
1890     }
1891 
1892     /**
1893      * Response from firmware to {@link #endDataPath(int)}.
1894      */
onEndDataPathResponse(short transactionId, boolean success, int reasonOnFailure)1895     public void onEndDataPathResponse(short transactionId, boolean success, int reasonOnFailure) {
1896         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1897         msg.arg1 = RESPONSE_TYPE_ON_END_DATA_PATH;
1898         msg.arg2 = transactionId;
1899         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success);
1900         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure);
1901         mSm.sendMessage(msg);
1902     }
1903 
1904     /**
1905      * Response from firmware to {@link #endPairing(int)}.
1906      */
onEndPairingResponse(short transactionId, boolean success, int reasonOnFailure)1907     public void onEndPairingResponse(short transactionId, boolean success, int reasonOnFailure) {
1908         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1909         msg.arg1 = RESPONSE_TYPE_ON_END_PAIRING;
1910         msg.arg2 = transactionId;
1911         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, success);
1912         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reasonOnFailure);
1913         mSm.sendMessage(msg);
1914     }
1915 
1916     /**
1917      * Response from firmware to {@link #suspend(int, int)}.
1918      */
onSuspendResponse(short transactionId, int status)1919     public void onSuspendResponse(short transactionId, int status) {
1920         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1921         msg.arg1 = RESPONSE_TYPE_ON_SUSPEND;
1922         msg.arg2 = transactionId;
1923         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, status == NanStatusCode.SUCCESS);
1924         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, status);
1925         mSm.sendMessage(msg);
1926     }
1927 
1928     /**
1929      * Response from firmware to {@link #resume(int, int)}.
1930      */
onResumeResponse(short transactionId, int status)1931     public void onResumeResponse(short transactionId, int status) {
1932         Message msg = mSm.obtainMessage(MESSAGE_TYPE_RESPONSE);
1933         msg.arg1 = RESPONSE_TYPE_ON_RESUME;
1934         msg.arg2 = transactionId;
1935         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, status == NanStatusCode.SUCCESS);
1936         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, status);
1937         mSm.sendMessage(msg);
1938     }
1939 
1940     /*
1941      * NOTIFICATIONS
1942      */
1943 
1944     /**
1945      * Place a callback request on the state machine queue: the discovery
1946      * interface has changed.
1947      */
onInterfaceAddressChangeNotification(byte[] mac)1948     public void onInterfaceAddressChangeNotification(byte[] mac) {
1949         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
1950         msg.arg1 = NOTIFICATION_TYPE_INTERFACE_CHANGE;
1951         msg.obj = mac;
1952         mSm.sendMessage(msg);
1953     }
1954 
1955     /**
1956      * Place a callback request on the state machine queue: the cluster
1957      * membership has changed (e.g. due to starting a new cluster or joining
1958      * another cluster).
1959      */
onClusterChangeNotification( @dentityChangedListener.ClusterChangeEvent int clusterEventType, byte[] clusterId)1960     public void onClusterChangeNotification(
1961             @IdentityChangedListener.ClusterChangeEvent int clusterEventType,
1962             byte[] clusterId) {
1963         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
1964         msg.arg1 = NOTIFICATION_TYPE_CLUSTER_CHANGE;
1965         msg.arg2 = clusterEventType;
1966         msg.obj = clusterId;
1967         mSm.sendMessage(msg);
1968     }
1969 
1970     /**
1971      * Place a callback request on the state machine queue: a discovery match
1972      * has occurred - e.g. our subscription discovered someone else publishing a
1973      * matching service (to the one we were looking for).
1974      */
onMatchNotification(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm, byte[] scid, int peerCipherSuite, byte[] nonce, byte[] tag, AwarePairingConfig pairingConfig, @Nullable List<OuiKeyedData> vendorData)1975     public void onMatchNotification(int pubSubId, int requestorInstanceId, byte[] peerMac,
1976             byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm,
1977             byte[] scid, int peerCipherSuite, byte[] nonce, byte[] tag,
1978             AwarePairingConfig pairingConfig, @Nullable List<OuiKeyedData> vendorData) {
1979         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
1980         msg.arg1 = NOTIFICATION_TYPE_MATCH;
1981         msg.arg2 = pubSubId;
1982         msg.getData().putInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID, requestorInstanceId);
1983         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac);
1984         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA, serviceSpecificInfo);
1985         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA, matchFilter);
1986         msg.getData().putInt(MESSAGE_RANGING_INDICATION, rangingIndication);
1987         msg.getData().putInt(MESSAGE_RANGE_MM, rangeMm);
1988         msg.getData().putInt(MESSAGE_BUNDLE_KEY_CIPHER_SUITE, peerCipherSuite);
1989         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_SCID, scid);
1990         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_NONCE, nonce);
1991         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_TAG, tag);
1992         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_PAIRING_CONFIG, pairingConfig);
1993         msg.getData().putParcelableArrayList(MESSAGE_BUNDLE_KEY_VENDOR_DATA,
1994                 vendorData != null ? new ArrayList<>(vendorData) : new ArrayList<>());
1995         mSm.sendMessage(msg);
1996     }
1997 
1998     /**
1999      * Place a callback request on the state machine queue: a discovered session
2000      * has expired - e.g. some discovered peer is no longer visible.
2001      */
onMatchExpiredNotification(int pubSubId, int requestorInstanceId)2002     public void onMatchExpiredNotification(int pubSubId, int requestorInstanceId) {
2003         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2004         msg.arg1 = NOTIFICATION_TYPE_MATCH_EXPIRED;
2005         msg.arg2 = pubSubId;
2006         msg.getData().putInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID, requestorInstanceId);
2007         mSm.sendMessage(msg);
2008     }
2009 
2010     /**
2011      * Place a callback request on the state machine queue: a session (publish
2012      * or subscribe) has terminated (per plan or due to an error).
2013      */
onSessionTerminatedNotification(int pubSubId, int reason, boolean isPublish)2014     public void onSessionTerminatedNotification(int pubSubId, int reason, boolean isPublish) {
2015         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2016         msg.arg1 = NOTIFICATION_TYPE_SESSION_TERMINATED;
2017         msg.arg2 = pubSubId;
2018         msg.obj = reason;
2019         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE, isPublish);
2020         mSm.sendMessage(msg);
2021     }
2022 
2023     /**
2024      * Place a callback request on the state machine queue: a message has been
2025      * received as part of a discovery session.
2026      */
onMessageReceivedNotification(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] message)2027     public void onMessageReceivedNotification(int pubSubId, int requestorInstanceId, byte[] peerMac,
2028             byte[] message) {
2029         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2030         msg.arg1 = NOTIFICATION_TYPE_MESSAGE_RECEIVED;
2031         msg.arg2 = pubSubId;
2032         msg.obj = requestorInstanceId;
2033         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac);
2034         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message);
2035         mSm.sendMessage(msg);
2036     }
2037 
2038     /**
2039      * Place a callback request on the state machine queue: Aware is going down.
2040      */
onAwareDownNotification(int reason)2041     public void onAwareDownNotification(int reason) {
2042         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2043         msg.arg1 = NOTIFICATION_TYPE_AWARE_DOWN;
2044         msg.arg2 = reason;
2045         mSm.sendMessage(msg);
2046     }
2047 
2048     /**
2049      * Notification that a message has been sent successfully (i.e. an ACK has been received).
2050      */
onMessageSendSuccessNotification(short transactionId)2051     public void onMessageSendSuccessNotification(short transactionId) {
2052         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2053         msg.arg1 = NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS;
2054         msg.arg2 = transactionId;
2055         mSm.sendMessage(msg);
2056     }
2057 
2058     /**
2059      * Notification that a message transmission has failed due to the indicated reason - e.g. no ACK
2060      * was received.
2061      */
onMessageSendFailNotification(short transactionId, int reason)2062     public void onMessageSendFailNotification(short transactionId, int reason) {
2063         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2064         msg.arg1 = NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL;
2065         msg.arg2 = transactionId;
2066         msg.obj = reason;
2067         mSm.sendMessage(msg);
2068     }
2069 
2070     /**
2071      * Place a callback request on the state machine queue: data-path request (from peer) received.
2072      */
onDataPathRequestNotification(int pubSubId, byte[] mac, int ndpId, byte[] message)2073     public void onDataPathRequestNotification(int pubSubId, byte[] mac, int ndpId, byte[] message) {
2074         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2075         msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST;
2076         msg.arg2 = pubSubId;
2077         msg.obj = ndpId;
2078         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac);
2079         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message);
2080         mSm.sendMessage(msg);
2081     }
2082 
2083     /**
2084      * Place a callback request on the state machine queue: data-path confirmation received - i.e.
2085      * data-path is now up.
2086      */
onDataPathConfirmNotification(int ndpId, byte[] mac, boolean accept, int reason, byte[] message, List<WifiAwareChannelInfo> channelInfo)2087     public void onDataPathConfirmNotification(int ndpId, byte[] mac, boolean accept, int reason,
2088             byte[] message, List<WifiAwareChannelInfo> channelInfo) {
2089         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2090         msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM;
2091         msg.arg2 = ndpId;
2092         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac);
2093         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG, accept);
2094         msg.getData().putInt(MESSAGE_BUNDLE_KEY_STATUS_CODE, reason);
2095         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA, message);
2096         msg.obj = channelInfo;
2097         mSm.sendMessage(msg);
2098     }
2099 
2100     /**
2101      * Place a callback request on the state machine queue: the specified data-path has been
2102      * terminated.
2103      */
onDataPathEndNotification(int ndpId)2104     public void onDataPathEndNotification(int ndpId) {
2105         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2106         msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_END;
2107         msg.arg2 = ndpId;
2108         mSm.sendMessage(msg);
2109     }
2110 
2111     /**
2112      * Place a callback request on the state machine queue: schedule update for the specified
2113      * data-paths.
2114      */
onDataPathScheduleUpdateNotification(byte[] peerMac, ArrayList<Integer> ndpIds, List<WifiAwareChannelInfo> channelInfo)2115     public void onDataPathScheduleUpdateNotification(byte[] peerMac, ArrayList<Integer> ndpIds,
2116             List<WifiAwareChannelInfo> channelInfo) {
2117         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2118         msg.arg1 = NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE;
2119         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, peerMac);
2120         msg.getData().putIntegerArrayList(MESSAGE_BUNDLE_KEY_NDP_IDS, ndpIds);
2121         msg.obj = channelInfo;
2122         mSm.sendMessage(msg);
2123     }
2124 
2125     /**
2126      * Place a callback request on the state machine queue: NAN Pairing request (from peer)
2127      * received.
2128      */
onPairingRequestNotification(int pubSubId, int requestorInstanceId, byte[] mac, int pairingId, int requestType, boolean enableCache, byte[] nonce, byte[] tag)2129     public void onPairingRequestNotification(int pubSubId, int requestorInstanceId, byte[] mac,
2130             int pairingId, int requestType, boolean enableCache, byte[] nonce, byte[] tag) {
2131         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2132         msg.arg1 = NOTIFICATION_TYPE_ON_PAIRING_REQUEST;
2133         msg.arg2 = pubSubId;
2134         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac);
2135         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID, pairingId);
2136         msg.getData().putInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID, requestorInstanceId);
2137         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE, requestType);
2138         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_PAIRING_CACHE, enableCache);
2139         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_NONCE, nonce);
2140         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_TAG, tag);
2141         mSm.sendMessage(msg);
2142     }
2143 
2144     /**
2145      * Place a callback request on the state machine queue: NAN Pairing confirm received.
2146      */
onPairingConfirmNotification(int pairingId, boolean accept, int reason, int requestType, boolean enableCache, PairingSecurityAssociationInfo npksa)2147     public void onPairingConfirmNotification(int pairingId, boolean accept, int reason,
2148             int requestType, boolean enableCache,
2149             PairingSecurityAssociationInfo npksa) {
2150         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2151         msg.arg1 = NOTIFICATION_TYPE_ON_PAIRING_CONFIRM;
2152         msg.arg2 = reason;
2153         msg.obj = npksa;
2154         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID, pairingId);
2155         msg.getData().putInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE, requestType);
2156         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_PAIRING_CACHE, enableCache);
2157         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_PAIRING_ACCEPT, accept);
2158         mSm.sendMessage(msg);
2159     }
2160 
2161     /**
2162      * Place a callback request on the state machine queue: bootstrapping request (from peer)
2163      * received.
2164      */
onBootstrappingRequestNotification(int pubSubId, int requestorInstanceId, byte[] mac, int bootstrappingInstanceId, int method)2165     public void onBootstrappingRequestNotification(int pubSubId, int requestorInstanceId,
2166             byte[] mac, int bootstrappingInstanceId, int method) {
2167         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2168         msg.arg1 = NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST;
2169         msg.arg2 = pubSubId;
2170         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS, mac);
2171         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID, bootstrappingInstanceId);
2172         msg.getData().putInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID, requestorInstanceId);
2173         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD, method);
2174         mSm.sendMessage(msg);
2175     }
2176 
2177     /**
2178      * Place a callback request on the state machine queue: bootstrapping confirm received.
2179      */
onBootstrappingConfirmNotification(int bootstrappingId, int responseCode, int reason, int comebackDelay, byte[] cookie)2180     public void onBootstrappingConfirmNotification(int bootstrappingId, int responseCode,
2181             int reason, int comebackDelay, byte[] cookie) {
2182         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2183         msg.arg1 = NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM;
2184         msg.arg2 = reason;
2185         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID, bootstrappingId);
2186         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_RESPONSE_CODE, responseCode);
2187         msg.getData().putInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_DELAY, comebackDelay);
2188         msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_COOKIE, cookie);
2189         mSm.sendMessage(msg);
2190     }
2191 
2192     /**
2193      * Place a callback request on the state machine queue: suspension mode changed.
2194      */
onSuspensionModeChangedNotification(boolean isSuspended)2195     public void onSuspensionModeChangedNotification(boolean isSuspended) {
2196         Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
2197         msg.arg1 = NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED;
2198         msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_SUSPENSION_MODE, isSuspended);
2199         mSm.sendMessage(msg);
2200     }
2201 
2202     /**
2203      * State machine.
2204      */
2205     @VisibleForTesting
2206     class WifiAwareStateMachine extends StateMachine {
2207         private static final int TRANSACTION_ID_IGNORE = 0;
2208 
2209         private final DefaultState mDefaultState;
2210         private final WaitState mWaitState;
2211         private final WaitForResponseState mWaitForResponseState;
2212         private final WaitingState mWaitingState = new WaitingState(this);
2213 
2214         private short mNextTransactionId = 1;
2215         public int mNextSessionId = 1;
2216 
2217         private Message mCurrentCommand;
2218         private short mCurrentTransactionId = TRANSACTION_ID_IGNORE;
2219 
2220         private static final long AWARE_SEND_MESSAGE_TIMEOUT = 10_000;
2221         private static final int MESSAGE_QUEUE_DEPTH_PER_UID = 50;
2222         private int mSendArrivalSequenceCounter = 0;
2223         private boolean mSendQueueBlocked = false;
2224         private final SparseArray<Message> mHostQueuedSendMessages = new SparseArray<>();
2225         private final Map<Short, Message> mFwQueuedSendMessages = new LinkedHashMap<>();
2226         private final WakeupMessage mSendMessageTimeoutMessage = new WakeupMessage(mContext,
2227                 getHandler(), HAL_SEND_MESSAGE_TIMEOUT_TAG, MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT);
2228 
2229         private static final long AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT = 20_000;
2230         private static final long AWARE_WAIT_FOR_PAIRING_CONFIRM_TIMEOUT = 20_000;
2231         private final SparseArray<WakeupMessage>
2232                 mDataPathConfirmTimeoutMessages = new SparseArray<>();
2233         private final SparseArray<WakeupMessage>
2234                 mPairingConfirmTimeoutMessages = new SparseArray<>();
2235         private final SparseArray<WakeupMessage>
2236                 mBootstrappingConfirmTimeoutMessages = new SparseArray<>();
2237 
WifiAwareStateMachine(String name, Looper looper)2238         WifiAwareStateMachine(String name, Looper looper) {
2239             super(name, looper);
2240             final int threshold = mContext.getResources().getInteger(
2241                     R.integer.config_wifiConfigurationWifiRunnerThresholdInMs);
2242             mDefaultState = new DefaultState(threshold);
2243             mWaitState = new WaitState(threshold);
2244             mWaitForResponseState = new WaitForResponseState(threshold);
2245             addState(mDefaultState);
2246             /* --> */ addState(mWaitState, mDefaultState);
2247             /* ----> */ addState(mWaitingState, mWaitState);
2248             /* --> */ addState(mWaitForResponseState, mDefaultState);
2249 
2250             setInitialState(mWaitState);
2251         }
2252 
2253         @Override
getWhatToString(int what)2254         protected String getWhatToString(int what) {
2255             return switch (what) {
2256                 case COMMAND_TYPE_CONNECT -> "COMMAND_TYPE_CONNECT";
2257                 case COMMAND_TYPE_DISCONNECT -> "COMMAND_TYPE_DISCONNECT";
2258                 case COMMAND_TYPE_TERMINATE_SESSION -> "COMMAND_TYPE_TERMINATE_SESSION";
2259                 case COMMAND_TYPE_PUBLISH -> "COMMAND_TYPE_PUBLISH";
2260                 case COMMAND_TYPE_UPDATE_PUBLISH -> "COMMAND_TYPE_UPDATE_PUBLISH";
2261                 case COMMAND_TYPE_SUBSCRIBE -> "COMMAND_TYPE_SUBSCRIBE";
2262                 case COMMAND_TYPE_UPDATE_SUBSCRIBE -> "COMMAND_TYPE_UPDATE_SUBSCRIBE";
2263                 case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE -> "COMMAND_TYPE_ENQUEUE_SEND_MESSAGE";
2264                 case COMMAND_TYPE_ENABLE_USAGE -> "COMMAND_TYPE_ENABLE_USAGE";
2265                 case COMMAND_TYPE_DISABLE_USAGE -> "COMMAND_TYPE_DISABLE_USAGE";
2266                 case COMMAND_TYPE_GET_CAPABILITIES -> "COMMAND_TYPE_GET_CAPABILITIES";
2267                 case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES
2268                         -> "COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES";
2269                 case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE
2270                         -> "COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE";
2271                 case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE
2272                         -> "COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE";
2273                 case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP
2274                         -> "COMMAND_TYPE_INITIATE_DATA_PATH_SETUP";
2275                 case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST
2276                         -> "COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST";
2277                 case COMMAND_TYPE_END_DATA_PATH -> "COMMAND_TYPE_END_DATA_PATH";
2278                 case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE -> "COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE";
2279                 case COMMAND_TYPE_RECONFIGURE -> "COMMAND_TYPE_RECONFIGURE";
2280                 case COMMAND_TYPE_DELAYED_INITIALIZATION -> "COMMAND_TYPE_DELAYED_INITIALIZATION";
2281                 case COMMAND_TYPE_GET_AWARE -> "COMMAND_TYPE_GET_AWARE";
2282                 case COMMAND_TYPE_RELEASE_AWARE -> "COMMAND_TYPE_RELEASE_AWARE";
2283                 case COMMAND_TYPE_DISABLE -> "COMMAND_TYPE_DISABLE";
2284                 case COMMAND_TYPE_INITIATE_PAIRING_REQUEST
2285                         -> "COMMAND_TYPE_INITIATE_PAIRING_REQUEST";
2286                 case COMMAND_TYPE_RESPONSE_PAIRING_REQUEST
2287                         -> "COMMAND_TYPE_RESPONSE_PAIRING_REQUEST";
2288                 case COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST
2289                         -> "COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST";
2290                 case COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST
2291                         -> "COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST";
2292                 case COMMAND_TYPE_SUSPEND_SESSION -> "COMMAND_TYPE_SUSPEND_SESSION";
2293                 case COMMAND_TYPE_RESUME_SESSION -> "COMMAND_TYPE_RESUME_SESSION";
2294                 case COMMAND_TYPE_END_PAIRING -> "COMMAND_TYPE_END_PAIRING";
2295 
2296                 case RESPONSE_TYPE_ON_CONFIG_SUCCESS -> "RESPONSE_TYPE_ON_CONFIG_SUCCESS";
2297                 case RESPONSE_TYPE_ON_CONFIG_FAIL -> "RESPONSE_TYPE_ON_CONFIG_FAIL";
2298                 case RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS
2299                         -> "RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS";
2300                 case RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL -> "RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL";
2301                 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS
2302                         -> "RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS";
2303                 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL
2304                         -> "RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL";
2305                 case RESPONSE_TYPE_ON_CAPABILITIES_UPDATED
2306                         -> "RESPONSE_TYPE_ON_CAPABILITIES_UPDATED";
2307                 case RESPONSE_TYPE_ON_CREATE_INTERFACE -> "RESPONSE_TYPE_ON_CREATE_INTERFACE";
2308                 case RESPONSE_TYPE_ON_DELETE_INTERFACE -> "RESPONSE_TYPE_ON_DELETE_INTERFACE";
2309                 case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS
2310                         -> "RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS";
2311                 case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL
2312                         -> "RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL";
2313                 case RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST
2314                         -> "RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST";
2315                 case RESPONSE_TYPE_ON_END_DATA_PATH -> "RESPONSE_TYPE_ON_END_DATA_PATH";
2316                 case RESPONSE_TYPE_ON_DISABLE -> "RESPONSE_TYPE_ON_DISABLE";
2317                 case RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS
2318                         -> "RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS";
2319                 case RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL
2320                         -> "RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL";
2321                 case RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS
2322                         -> "RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS";
2323                 case RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL
2324                         -> "RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL";
2325                 case RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS
2326                         -> "RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS";
2327                 case RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL
2328                         -> "RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL";
2329                 case RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS
2330                         -> "RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS";
2331                 case RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL
2332                         -> "RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL";
2333                 case RESPONSE_TYPE_ON_SUSPEND -> "RESPONSE_TYPE_ON_SUSPEND";
2334                 case RESPONSE_TYPE_ON_RESUME -> "RESPONSE_TYPE_ON_RESUME";
2335                 case RESPONSE_TYPE_ON_END_PAIRING -> "RESPONSE_TYPE_ON_END_PAIRING";
2336 
2337                 case NOTIFICATION_TYPE_INTERFACE_CHANGE -> "NOTIFICATION_TYPE_INTERFACE_CHANGE";
2338                 case NOTIFICATION_TYPE_CLUSTER_CHANGE -> "NOTIFICATION_TYPE_CLUSTER_CHANGE";
2339                 case NOTIFICATION_TYPE_MATCH -> "NOTIFICATION_TYPE_MATCH";
2340                 case NOTIFICATION_TYPE_SESSION_TERMINATED -> "NOTIFICATION_TYPE_SESSION_TERMINATED";
2341                 case NOTIFICATION_TYPE_MESSAGE_RECEIVED -> "NOTIFICATION_TYPE_MESSAGE_RECEIVED";
2342                 case NOTIFICATION_TYPE_AWARE_DOWN -> "NOTIFICATION_TYPE_AWARE_DOWN";
2343                 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS
2344                         -> "NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS";
2345                 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL
2346                         -> "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL";
2347                 case NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST
2348                         -> "NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST";
2349                 case NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM
2350                         -> "NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM";
2351                 case NOTIFICATION_TYPE_ON_DATA_PATH_END -> "NOTIFICATION_TYPE_ON_DATA_PATH_END";
2352                 case NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE
2353                         -> "NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE";
2354                 case NOTIFICATION_TYPE_MATCH_EXPIRED -> "NOTIFICATION_TYPE_MATCH_EXPIRED";
2355                 case NOTIFICATION_TYPE_ON_PAIRING_REQUEST -> "NOTIFICATION_TYPE_ON_PAIRING_REQUEST";
2356                 case NOTIFICATION_TYPE_ON_PAIRING_CONFIRM -> "NOTIFICATION_TYPE_ON_PAIRING_CONFIRM";
2357                 case NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST
2358                         -> "NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST";
2359                 case NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM
2360                         -> "NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM";
2361                 case NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED
2362                         -> "NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED";
2363                 case RunnerState.STATE_ENTER_CMD -> "Enter";
2364                 case RunnerState.STATE_EXIT_CMD -> "Exit";
2365                 case MESSAGE_TYPE_COMMAND -> "MESSAGE_TYPE_COMMAND";
2366                 case MESSAGE_TYPE_RESPONSE -> "MESSAGE_TYPE_RESPONSE";
2367                 case MESSAGE_TYPE_NOTIFICATION -> "MESSAGE_TYPE_NOTIFICATION";
2368                 case MESSAGE_TYPE_RESPONSE_TIMEOUT -> "MESSAGE_TYPE_RESPONSE_TIMEOUT";
2369                 case MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT -> "MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT";
2370                 case MESSAGE_TYPE_DATA_PATH_TIMEOUT -> "MESSAGE_TYPE_DATA_PATH_TIMEOUT";
2371                 case MESSAGE_TYPE_PAIRING_TIMEOUT -> "MESSAGE_TYPE_PAIRING_TIMEOUT";
2372                 case MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT -> "MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT";
2373                 default -> {
2374                     Log.e(TAG, "unknown message what: " + what);
2375                     yield "what:" + what;
2376                 }
2377             };
2378         }
2379 
messageToString(Message msg)2380         private String messageToString(Message msg) {
2381             StringBuilder sb = new StringBuilder();
2382 
2383             String s = getWhatToString(msg.what);
2384             if (s == null) {
2385                 s = "<unknown>";
2386             }
2387             sb.append(s).append("/");
2388 
2389             if (msg.what == MESSAGE_TYPE_NOTIFICATION || msg.what == MESSAGE_TYPE_COMMAND
2390                     || msg.what == MESSAGE_TYPE_RESPONSE) {
2391                 s = getWhatToString(msg.arg1);
2392                 if (s == null) {
2393                     s = "<unknown>";
2394                 }
2395                 sb.append(s);
2396             }
2397 
2398             if (msg.what == MESSAGE_TYPE_RESPONSE || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) {
2399                 sb.append(" (Transaction ID=").append(msg.arg2).append(")");
2400             }
2401 
2402             return sb.toString();
2403         }
2404 
onAwareDownCleanupSendQueueState()2405         public void onAwareDownCleanupSendQueueState() {
2406             mSendQueueBlocked = false;
2407             mHostQueuedSendMessages.clear();
2408             mFwQueuedSendMessages.clear();
2409         }
2410 
2411         private class DefaultState extends RunnerState {
2412 
DefaultState(int threshold)2413             DefaultState(int threshold) {
2414                 super(threshold, mWifiInjector.getWifiHandlerLocalLog());
2415             }
2416 
2417             @Override
getMessageLogRec(Message message)2418             public String getMessageLogRec(Message message) {
2419                 return WifiAwareStateManager.class.getSimpleName() + "."
2420                         + DefaultState.class.getSimpleName() + "." + getWhatToString(message.what)
2421                         + "#" + getWhatToString(message.arg1);
2422             }
2423 
2424             @Override
enterImpl()2425             public void enterImpl() {
2426             }
2427 
2428             @Override
exitImpl()2429             public void exitImpl() {
2430             }
2431             @Override
processMessageImpl(Message msg)2432             public boolean processMessageImpl(Message msg) {
2433                 if (mVdbg) {
2434                     Log.v(TAG, getName() + msg.toString());
2435                 }
2436 
2437                 switch (msg.what) {
2438                     case MESSAGE_TYPE_NOTIFICATION:
2439                         processNotification(msg);
2440                         return HANDLED;
2441                     case MESSAGE_TYPE_SEND_MESSAGE_TIMEOUT:
2442                         processSendMessageTimeout();
2443                         return HANDLED;
2444                     case MESSAGE_TYPE_DATA_PATH_TIMEOUT: {
2445                         int ndpId = msg.arg1;
2446 
2447                         if (mVerboseLoggingEnabled) {
2448                             Log.v(TAG, "MESSAGE_TYPE_DATA_PATH_TIMEOUT: ndpId="
2449                                     + ndpId);
2450                         }
2451 
2452                         mDataPathMgr.handleDataPathTimeout(ndpId);
2453                         mDataPathConfirmTimeoutMessages.remove(ndpId);
2454                         return HANDLED;
2455                     }
2456                     case MESSAGE_TYPE_PAIRING_TIMEOUT: {
2457                         int pairId = msg.arg1;
2458                         endPairing(pairId);
2459                         onPairingConfirmNotification(pairId, false,
2460                                 NanStatusCode.INTERNAL_FAILURE, msg.arg2, false, null);
2461                         mPairingConfirmTimeoutMessages.remove(pairId);
2462                         return HANDLED;
2463                     }
2464                     case MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT: {
2465                         int bootstrappingId = msg.arg1;
2466                         onBootstrappingConfirmNotification(bootstrappingId,
2467                                 NAN_BOOTSTRAPPING_REJECT, NanStatusCode.INTERNAL_FAILURE, 0, null);
2468                         mBootstrappingConfirmTimeoutMessages.remove(bootstrappingId);
2469                         return HANDLED;
2470                     }
2471                     default:
2472                         /* fall-through */
2473                 }
2474 
2475                 Log.wtf(TAG,
2476                         "DefaultState: should not get non-NOTIFICATION in this state: msg=" + msg);
2477                 return NOT_HANDLED;
2478             }
2479         }
2480 
2481         private class WaitState extends RunnerState {
2482 
WaitState(int threshold)2483             WaitState(int threshold) {
2484                 super(threshold, mWifiInjector.getWifiHandlerLocalLog());
2485             }
2486 
2487             @Override
getMessageLogRec(Message message)2488             public String getMessageLogRec(Message message) {
2489                 return WifiAwareStateManager.class.getSimpleName() + "."
2490                         + WaitState.class.getSimpleName() + "." + getWhatToString(message.what)
2491                         + "#" + getWhatToString(message.arg1);
2492             }
2493 
2494             @Override
enterImpl()2495             public void enterImpl() {
2496             }
2497 
2498             @Override
exitImpl()2499             public void exitImpl() {
2500             }
2501             @Override
processMessageImpl(Message msg)2502             public boolean processMessageImpl(Message msg) {
2503                 if (mVdbg) {
2504                     Log.v(TAG, getName() + msg.toString());
2505                 }
2506 
2507                 switch (msg.what) {
2508                     case MESSAGE_TYPE_COMMAND:
2509                         if (processCommand(msg)) {
2510                             transitionTo(mWaitForResponseState);
2511                         }
2512                         return HANDLED;
2513                     case MESSAGE_TYPE_RESPONSE:
2514                         /* fall-through */
2515                     case MESSAGE_TYPE_RESPONSE_TIMEOUT:
2516                         /*
2517                          * remnants/delayed/out-of-sync messages - but let
2518                          * WaitForResponseState deal with them (identified as
2519                          * out-of-date by transaction ID).
2520                          */
2521                         deferMessage(msg);
2522                         return HANDLED;
2523                     default:
2524                         /* fall-through */
2525                 }
2526 
2527                 return NOT_HANDLED;
2528             }
2529         }
2530 
2531         private class WaitForResponseState extends RunnerState {
2532             private static final long AWARE_COMMAND_TIMEOUT = 5_000;
2533             private WakeupMessage mTimeoutMessage;
2534 
WaitForResponseState(int threshold)2535             WaitForResponseState(int threshold) {
2536                 super(threshold, mWifiInjector.getWifiHandlerLocalLog());
2537             }
2538 
2539             @Override
getMessageLogRec(Message message)2540             public String getMessageLogRec(Message message) {
2541                 return WifiAwareStateManager.class.getSimpleName() + "."
2542                         + WaitForResponseState.class.getSimpleName() + "."
2543                         + getWhatToString(message.what) + "#" + getWhatToString(message.arg1);
2544             }
2545 
2546             @Override
enterImpl()2547             public void enterImpl() {
2548                 mTimeoutMessage = new WakeupMessage(mContext, getHandler(), HAL_COMMAND_TIMEOUT_TAG,
2549                         MESSAGE_TYPE_RESPONSE_TIMEOUT, mCurrentCommand.arg1, mCurrentTransactionId);
2550                 mTimeoutMessage.schedule(SystemClock.elapsedRealtime() + AWARE_COMMAND_TIMEOUT);
2551                 mStartTime = SystemClock.elapsedRealtime();
2552             }
2553 
2554             @Override
exitImpl()2555             public void exitImpl() {
2556                 mTimeoutMessage.cancel();
2557             }
2558 
2559             @Override
processMessageImpl(Message msg)2560             public boolean processMessageImpl(Message msg) {
2561                 if (mVdbg) {
2562                     Log.v(TAG, getName() + msg.toString());
2563                 }
2564 
2565                 switch (msg.what) {
2566                     case MESSAGE_TYPE_COMMAND:
2567                         /*
2568                          * don't want COMMANDs in this state - defer until back
2569                          * in WaitState
2570                          */
2571                         deferMessage(msg);
2572                         return HANDLED;
2573                     case MESSAGE_TYPE_RESPONSE:
2574                         if (msg.arg2 == mCurrentTransactionId) {
2575                             processResponse(msg);
2576                             transitionTo(mWaitState);
2577                         } else {
2578                             Log.w(TAG,
2579                                     "WaitForResponseState: processMessage: non-matching "
2580                                             + "transaction ID on RESPONSE (a very late "
2581                                             + "response) -- msg=" + msg);
2582                             /* no transition */
2583                         }
2584                         return HANDLED;
2585                     case MESSAGE_TYPE_RESPONSE_TIMEOUT:
2586                         if (msg.arg2 == mCurrentTransactionId) {
2587                             processTimeout(msg);
2588                             transitionTo(mWaitState);
2589                         } else {
2590                             Log.w(TAG, "WaitForResponseState: processMessage: non-matching "
2591                                     + "transaction ID on RESPONSE_TIMEOUT (either a non-cancelled "
2592                                     + "timeout or a race condition with cancel) -- msg=" + msg);
2593                             /* no transition */
2594                         }
2595                         return HANDLED;
2596                     default:
2597                         /* fall-through */
2598                 }
2599 
2600                 return NOT_HANDLED;
2601             }
2602         }
2603 
processNotification(Message msg)2604         private void processNotification(Message msg) {
2605             if (mVdbg) {
2606                 Log.v(TAG, "processNotification: msg=" + msg);
2607             }
2608 
2609             switch (msg.arg1) {
2610                 case NOTIFICATION_TYPE_INTERFACE_CHANGE: {
2611                     byte[] mac = (byte[]) msg.obj;
2612 
2613                     onInterfaceAddressChangeLocal(mac);
2614                     break;
2615                 }
2616                 case NOTIFICATION_TYPE_CLUSTER_CHANGE: {
2617                     int clusterEventType = msg.arg2;
2618                     byte[] clusterId = (byte[]) msg.obj;
2619 
2620                     onClusterChangeLocal(clusterEventType, clusterId);
2621                     break;
2622                 }
2623                 case NOTIFICATION_TYPE_MATCH: {
2624                     int pubSubId = msg.arg2;
2625                     int requesterInstanceId = msg.getData()
2626                             .getInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID);
2627                     byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
2628                     byte[] serviceSpecificInfo = msg.getData()
2629                             .getByteArray(MESSAGE_BUNDLE_KEY_SSI_DATA);
2630                     byte[] matchFilter = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_FILTER_DATA);
2631                     int rangingIndication = msg.getData().getInt(MESSAGE_RANGING_INDICATION);
2632                     int rangeMm = msg.getData().getInt(MESSAGE_RANGE_MM);
2633                     int cipherSuite = msg.getData().getInt(MESSAGE_BUNDLE_KEY_CIPHER_SUITE);
2634                     byte[] scid = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_SCID);
2635                     byte[] nonce = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_NONCE);
2636                     byte[] tag = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_TAG);
2637                     AwarePairingConfig pairingConfig = msg.getData()
2638                             .getParcelable(MESSAGE_BUNDLE_KEY_PAIRING_CONFIG);
2639                     ArrayList<OuiKeyedData> vendorData =
2640                             msg.getData().getParcelableArrayList(MESSAGE_BUNDLE_KEY_VENDOR_DATA);
2641 
2642                     onMatchLocal(pubSubId, requesterInstanceId, peerMac, serviceSpecificInfo,
2643                             matchFilter, rangingIndication, rangeMm, cipherSuite, scid, nonce, tag,
2644                             pairingConfig, vendorData);
2645                     break;
2646                 }
2647                 case NOTIFICATION_TYPE_MATCH_EXPIRED: {
2648                     int pubSubId = msg.arg2;
2649                     int requestorInstanceId = msg.getData()
2650                             .getInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID);
2651                     onMatchExpiredLocal(pubSubId, requestorInstanceId);
2652                     break;
2653                 }
2654                 case NOTIFICATION_TYPE_SESSION_TERMINATED: {
2655                     int pubSubId = msg.arg2;
2656                     int reason = (Integer) msg.obj;
2657                     boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE);
2658 
2659                     onSessionTerminatedLocal(pubSubId, isPublish, reason);
2660                     break;
2661                 }
2662                 case NOTIFICATION_TYPE_MESSAGE_RECEIVED: {
2663                     int pubSubId = msg.arg2;
2664                     int requestorInstanceId = (Integer) msg.obj;
2665                     byte[] peerMac = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
2666                     byte[] message = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA);
2667 
2668                     onMessageReceivedLocal(pubSubId, requestorInstanceId, peerMac, message);
2669                     break;
2670                 }
2671                 case NOTIFICATION_TYPE_AWARE_DOWN: {
2672                     int reason = msg.arg2;
2673 
2674                     /*
2675                      * TODO: b/28615938. Use reason code to determine whether or not need clean-up
2676                      * local state (only needed if AWARE_DOWN is due to internal firmware reason,
2677                      * e.g. concurrency, rather than due to a requested shutdown).
2678                      */
2679 
2680                     onAwareDownLocal();
2681                     if (reason != NanStatusCode.SUCCESS) {
2682                         sendAwareStateChangedBroadcast(false);
2683                     }
2684                     break;
2685                 }
2686                 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: {
2687                     short transactionId = (short) msg.arg2;
2688                     Message queuedSendCommand = mFwQueuedSendMessages.get(transactionId);
2689                     if (mVdbg) {
2690                         Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: queuedSendCommand="
2691                                 + queuedSendCommand);
2692                     }
2693                     if (queuedSendCommand == null) {
2694                         Log.w(TAG,
2695                                 "processNotification: NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS:"
2696                                         + " transactionId=" + transactionId
2697                                         + " - no such queued send command (timed-out?)");
2698                     } else {
2699                         mFwQueuedSendMessages.remove(transactionId);
2700                         updateSendMessageTimeout();
2701                         onMessageSendSuccessLocal(queuedSendCommand);
2702                     }
2703                     mSendQueueBlocked = false;
2704                     transmitNextMessage();
2705 
2706                     break;
2707                 }
2708                 case NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: {
2709                     short transactionId = (short) msg.arg2;
2710                     int reason = (Integer) msg.obj;
2711                     Message sentMessage = mFwQueuedSendMessages.get(transactionId);
2712                     if (mVdbg) {
2713                         Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: sentMessage="
2714                                 + sentMessage);
2715                     }
2716                     if (sentMessage == null) {
2717                         Log.w(TAG,
2718                                 "processNotification: NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL:"
2719                                         + " transactionId=" + transactionId
2720                                         + " - no such queued send command (timed-out?)");
2721                     } else {
2722                         mFwQueuedSendMessages.remove(transactionId);
2723                         updateSendMessageTimeout();
2724 
2725                         int retryCount = sentMessage.getData()
2726                                 .getInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT);
2727                         if (retryCount > 0 && reason == NanStatusCode.NO_OTA_ACK) {
2728                             if (mVerboseLoggingEnabled) {
2729                                 Log.v(TAG,
2730                                         "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: transactionId="
2731                                                 + transactionId + ", reason=" + reason
2732                                                 + ": retransmitting - retryCount=" + retryCount);
2733                             }
2734                             sentMessage.getData().putInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT,
2735                                     retryCount - 1);
2736 
2737                             int arrivalSeq = sentMessage.getData().getInt(
2738                                     MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ);
2739                             mHostQueuedSendMessages.put(arrivalSeq, sentMessage);
2740                         } else {
2741                             onMessageSendFailLocal(sentMessage, reason);
2742                         }
2743                         mSendQueueBlocked = false;
2744                         transmitNextMessage();
2745                     }
2746                     break;
2747                 }
2748                 case NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST: {
2749                     int ndpId = (int) msg.obj;
2750                     mDataPathMgr.onDataPathRequest(
2751                             msg.arg2, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS),
2752                             ndpId, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE));
2753 
2754                     break;
2755                 }
2756                 case NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM: {
2757                     int ndpId = msg.arg2;
2758                     boolean success = mDataPathMgr.onDataPathConfirm(
2759                             ndpId, msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS),
2760                             msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG),
2761                             msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE),
2762                             msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE_DATA),
2763                             (List<WifiAwareChannelInfo>) msg.obj);
2764 
2765                     if (success) {
2766                         WakeupMessage timeout = mDataPathConfirmTimeoutMessages.get(ndpId);
2767                         if (timeout != null) {
2768                             mDataPathConfirmTimeoutMessages.remove(ndpId);
2769                             timeout.cancel();
2770                         }
2771                     }
2772 
2773                     break;
2774                 }
2775                 case NOTIFICATION_TYPE_ON_DATA_PATH_END:
2776                     mDataPathMgr.onDataPathEnd(msg.arg2);
2777                     sendAwareResourcesChangedBroadcast();
2778                     break;
2779                 case NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE:
2780                     mDataPathMgr.onDataPathSchedUpdate(
2781                             msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS),
2782                             msg.getData().getIntegerArrayList(MESSAGE_BUNDLE_KEY_NDP_IDS),
2783                             (List<WifiAwareChannelInfo>) msg.obj);
2784                     break;
2785                 case NOTIFICATION_TYPE_ON_PAIRING_REQUEST: {
2786                     Bundle data = msg.getData();
2787                     int pubSubId = msg.arg2;
2788                     int pairId = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID);
2789                     int requestorInstanceId = data.getInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID);
2790                     byte[] mac = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
2791                     int requestType = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE);
2792                     byte[] nonce = data.getByteArray(MESSAGE_BUNDLE_KEY_NONCE);
2793                     byte[] tag = data.getByteArray(MESSAGE_BUNDLE_KEY_TAG);
2794                     onPairingRequestReceivedLocal(pubSubId, requestorInstanceId, mac, pairId,
2795                             requestType, nonce, tag);
2796                     break;
2797                 }
2798                 case NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST: {
2799                     Bundle data = msg.getData();
2800                     int pubSubId = msg.arg2;
2801                     int bootStrappingId = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID);
2802                     int requestorInstanceId = data.getInt(MESSAGE_BUNDLE_KEY_REQ_INSTANCE_ID);
2803                     byte[] mac = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
2804                     int method = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD);
2805                     onBootstrappingRequestReceivedLocal(pubSubId, requestorInstanceId, mac,
2806                             bootStrappingId, method);
2807                     break;
2808                 }
2809                 case NOTIFICATION_TYPE_ON_PAIRING_CONFIRM: {
2810                     Bundle data = msg.getData();
2811                     int reason = msg.arg2;
2812                     PairingSecurityAssociationInfo npksa = (PairingSecurityAssociationInfo) msg.obj;
2813                     int pairId = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID);
2814                     boolean accept = data.getBoolean(MESSAGE_BUNDLE_KEY_PAIRING_ACCEPT);
2815                     boolean enableCache = data.getBoolean(MESSAGE_BUNDLE_KEY_PAIRING_CACHE);
2816                     int requestType = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE);
2817                     boolean success = onPairingConfirmReceivedLocal(pairId, accept, reason,
2818                             requestType, enableCache, npksa);
2819                     if (success) {
2820                         WakeupMessage timeout = mPairingConfirmTimeoutMessages.get(pairId);
2821                         if (timeout != null) {
2822                             mPairingConfirmTimeoutMessages.remove(pairId);
2823                             timeout.cancel();
2824                         }
2825                     }
2826                     break;
2827                 }
2828                 case NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM: {
2829                     Bundle data = msg.getData();
2830                     int reason = msg.arg2;
2831                     int bootstrappingId = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID);
2832                     int responseCode = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_RESPONSE_CODE);
2833                     int comBackDelay = data.getInt(
2834                             MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_DELAY);
2835                     byte[] cookie = data.getByteArray(
2836                             MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_COOKIE);
2837                     boolean success = onBootStrappingConfirmReceivedLocal(bootstrappingId,
2838                             reason, responseCode, comBackDelay, cookie);
2839                     if (success) {
2840                         WakeupMessage timeout = mBootstrappingConfirmTimeoutMessages
2841                                 .get(bootstrappingId);
2842                         if (timeout != null) {
2843                             mBootstrappingConfirmTimeoutMessages.remove(bootstrappingId);
2844                             timeout.cancel();
2845                         }
2846                     }
2847                     break;
2848                 }
2849                 case NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED: {
2850                     Bundle data = msg.getData();
2851                     boolean isSuspended = data.getBoolean(MESSAGE_BUNDLE_KEY_SUSPENSION_MODE);
2852                     onSuspensionModeChangedLocal(isSuspended);
2853                     break;
2854                 }
2855                 default:
2856                     Log.wtf(TAG, "processNotification: this isn't a NOTIFICATION -- msg=" + msg);
2857             }
2858         }
2859 
2860         /**
2861          * Execute the command specified by the input Message. Returns a true if
2862          * need to wait for a RESPONSE, otherwise a false. We may not have to
2863          * wait for a RESPONSE if there was an error in the state (so no command
2864          * is sent to HAL) OR if we choose not to wait for response - e.g. for
2865          * disconnected/terminate commands failure is not possible.
2866          */
processCommand(Message msg)2867         private boolean processCommand(Message msg) {
2868             if (mVdbg) {
2869                 Log.v(TAG, "processCommand: msg=" + msg);
2870             }
2871 
2872             if (mCurrentCommand != null) {
2873                 Log.wtf(TAG,
2874                         "processCommand: receiving a command (msg=" + msg
2875                                 + ") but current (previous) command isn't null (prev_msg="
2876                                 + mCurrentCommand + ")");
2877                 mCurrentCommand = null;
2878             }
2879 
2880             mCurrentTransactionId = mNextTransactionId++;
2881 
2882             boolean waitForResponse = true;
2883 
2884             switch (msg.arg1) {
2885                 case COMMAND_TYPE_CONNECT: {
2886                     if (mAwareIsDisabling) {
2887                         deferMessage(msg);
2888                         waitForResponse = false;
2889                         if (WaitingState.wasMessageInWaitingState(msg)) {
2890                             mInterfaceConflictMgr.reset();
2891                         }
2892                         break;
2893                     }
2894 
2895                     int clientId = msg.arg2;
2896                     Pair<IWifiAwareEventCallback, Object> callbackAndAttributionSource =
2897                             (Pair<IWifiAwareEventCallback, Object>) msg.obj;
2898                     IWifiAwareEventCallback callback = callbackAndAttributionSource.first;
2899                     ConfigRequest configRequest = (ConfigRequest) msg.getData()
2900                             .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
2901                     int uid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_UID);
2902                     int pid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_PID);
2903                     String callingPackage = msg.getData().getString(
2904                             MESSAGE_BUNDLE_KEY_CALLING_PACKAGE);
2905                     String callingFeatureId = msg.getData().getString(
2906                             MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID);
2907                     boolean notifyIdentityChange = msg.getData().getBoolean(
2908                             MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE);
2909                     boolean awareOffload = msg.getData().getBoolean(
2910                             MESSAGE_BUNDLE_KEY_AWARE_OFFLOAD);
2911                     boolean reEnableAware = msg.getData()
2912                             .getBoolean(MESSAGE_BUNDLE_KEY_RE_ENABLE_AWARE_FROM_OFFLOAD);
2913                     int callerType = msg.getData().getInt(MESSAGE_BUNDLE_KEY_CALLER_TYPE);
2914                     int proceedWithOperation =
2915                             mInterfaceConflictMgr.manageInterfaceConflictForStateMachine(TAG,
2916                                     msg, this, mWaitingState, mWaitState,
2917                                     HalDeviceManager.HDM_CREATE_IFACE_NAN,
2918                                     new WorkSource(uid, callingPackage),
2919                                     awareOffload || mOpportunisticSet.contains(callingPackage)
2920                                     /* bypassDialog */);
2921 
2922                     if (proceedWithOperation == InterfaceConflictManager.ICM_ABORT_COMMAND) {
2923                         // handling user rejection or possible conflict (pending command)
2924                         try {
2925                             callback.onConnectFail(
2926                                     NanStatusCode.NO_RESOURCES_AVAILABLE);
2927                             mAwareMetrics.recordAttachStatus(NanStatusCode.NO_RESOURCES_AVAILABLE,
2928                                     callerType, callingFeatureId, uid);
2929                         } catch (RemoteException e) {
2930                             Log.w(TAG, "displayUserApprovalDialog user refusal: RemoteException "
2931                                     + "(FYI): " + e);
2932                         }
2933                         waitForResponse = false;
2934                     } else if (proceedWithOperation
2935                             == InterfaceConflictManager.ICM_EXECUTE_COMMAND) {
2936                         waitForResponse = connectLocal(mCurrentTransactionId, clientId, uid, pid,
2937                                 callingPackage, callingFeatureId, callback, configRequest,
2938                                 notifyIdentityChange,
2939                                 callbackAndAttributionSource.second,
2940                                 awareOffload, reEnableAware, callerType);
2941                     } else { // InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER
2942                         waitForResponse = false;
2943                     }
2944                     break;
2945                 }
2946                 case COMMAND_TYPE_DISCONNECT: {
2947                     int clientId = msg.arg2;
2948 
2949                     waitForResponse = disconnectLocal(mCurrentTransactionId, clientId);
2950                     break;
2951                 }
2952                 case COMMAND_TYPE_DISABLE: {
2953                     mAwareIsDisabling = false;
2954                     // Must trigger a state transition to execute the deferred connect command
2955                     if (!mWifiAwareNativeApi.disable(mCurrentTransactionId)) {
2956                         onDisableResponse(mCurrentTransactionId, WifiStatusCode.ERROR_UNKNOWN);
2957                     }
2958                     break;
2959                 }
2960                 case COMMAND_TYPE_RECONFIGURE:
2961                     waitForResponse = reconfigureLocal(mCurrentTransactionId);
2962                     break;
2963                 case COMMAND_TYPE_TERMINATE_SESSION: {
2964                     int clientId = msg.arg2;
2965                     int sessionId = (Integer) msg.obj;
2966 
2967                     terminateSessionLocal(clientId, sessionId);
2968                     waitForResponse = false;
2969                     break;
2970                 }
2971                 case COMMAND_TYPE_PUBLISH: {
2972                     int clientId = msg.arg2;
2973                     IWifiAwareDiscoverySessionCallback callback =
2974                             (IWifiAwareDiscoverySessionCallback) msg.obj;
2975                     PublishConfig publishConfig = (PublishConfig) msg.getData()
2976                             .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
2977 
2978                     waitForResponse = publishLocal(mCurrentTransactionId, clientId, publishConfig,
2979                             callback);
2980                     break;
2981                 }
2982                 case COMMAND_TYPE_UPDATE_PUBLISH: {
2983                     int clientId = msg.arg2;
2984                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
2985                     PublishConfig publishConfig = (PublishConfig) msg.getData()
2986                             .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
2987                     waitForResponse = updatePublishLocal(mCurrentTransactionId, clientId, sessionId,
2988                             publishConfig);
2989                     break;
2990                 }
2991                 case COMMAND_TYPE_SUBSCRIBE: {
2992                     int clientId = msg.arg2;
2993                     IWifiAwareDiscoverySessionCallback callback =
2994                             (IWifiAwareDiscoverySessionCallback) msg.obj;
2995                     SubscribeConfig subscribeConfig = (SubscribeConfig) msg.getData()
2996                             .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
2997 
2998                     waitForResponse = subscribeLocal(mCurrentTransactionId, clientId,
2999                             subscribeConfig, callback);
3000                     break;
3001                 }
3002                 case COMMAND_TYPE_UPDATE_SUBSCRIBE: {
3003                     int clientId = msg.arg2;
3004                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3005                     SubscribeConfig subscribeConfig = (SubscribeConfig) msg.getData()
3006                             .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
3007 
3008                     waitForResponse = updateSubscribeLocal(mCurrentTransactionId, clientId,
3009                             sessionId, subscribeConfig);
3010                     break;
3011                 }
3012                 case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: {
3013                     if (mVdbg) {
3014                         Log.v(TAG, "processCommand: ENQUEUE_SEND_MESSAGE - messageId="
3015                                 + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID)
3016                                 + ", mSendArrivalSequenceCounter=" + mSendArrivalSequenceCounter);
3017                     }
3018                     int uid = msg.getData().getInt(MESSAGE_BUNDLE_KEY_UID);
3019                     if (isUidExceededMessageQueueDepthLimit(uid)) {
3020                         if (mVerboseLoggingEnabled) {
3021                             Log.v(TAG, "message queue limit exceeded for uid=" + uid
3022                                     + " at messageId="
3023                                     + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID));
3024                         }
3025                         onMessageSendFailLocal(msg, NanStatusCode.INTERNAL_FAILURE);
3026                         waitForResponse = false;
3027                         break;
3028                     }
3029                     Message sendMsg = obtainMessage(msg.what);
3030                     sendMsg.copyFrom(msg);
3031                     sendMsg.getData().putInt(MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ,
3032                             mSendArrivalSequenceCounter);
3033                     mHostQueuedSendMessages.put(mSendArrivalSequenceCounter, sendMsg);
3034                     mSendArrivalSequenceCounter++;
3035                     waitForResponse = false;
3036 
3037                     if (!mSendQueueBlocked) {
3038                         transmitNextMessage();
3039                     }
3040 
3041                     break;
3042                 }
3043                 case COMMAND_TYPE_INITIATE_PAIRING_REQUEST: {
3044                     int clientId = msg.arg2;
3045                     Bundle data = msg.getData();
3046                     int sessionId = data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3047                     int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID);
3048                     String password = data.getString(MESSAGE_BUNDLE_KEY_PAIRING_PASSWORD);
3049                     int requestType = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE);
3050                     int akm = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_AKM);
3051                     int cipherSuite = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_CIPHER_SUITE);
3052                     byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PAIRING_PMK);
3053                     waitForResponse = initiateNanPairingRequestLocal(mCurrentTransactionId,
3054                             clientId, sessionId, peerId, password, requestType, akm, pmk,
3055                             cipherSuite);
3056                     break;
3057                 }
3058                 case COMMAND_TYPE_RESPONSE_PAIRING_REQUEST: {
3059                     int clientId = msg.arg2;
3060                     Bundle data = msg.getData();
3061                     int sessionId = data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3062                     int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID);
3063                     int requestId = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID);
3064                     String password = data.getString(MESSAGE_BUNDLE_KEY_PAIRING_PASSWORD);
3065                     int requestType = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE);
3066                     int akm = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_AKM);
3067                     int cipherSuite = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_CIPHER_SUITE);
3068                     byte[] pmk = data.getByteArray(MESSAGE_BUNDLE_KEY_PAIRING_PMK);
3069                     boolean accept = data.getBoolean(MESSAGE_BUNDLE_KEY_PAIRING_ACCEPT);
3070                     waitForResponse = respondToPairingRequestLocal(mCurrentTransactionId, clientId,
3071                             sessionId, peerId, requestId, accept, requestType, pmk, password, akm,
3072                             cipherSuite);
3073                     break;
3074                 }
3075                 case COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST: {
3076                     int clientId = msg.arg2;
3077                     Bundle data = msg.getData();
3078                     int sessionId = data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3079                     int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID);
3080                     int method = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD);
3081                     byte[] cookie = data.getByteArray(
3082                             MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_COME_BACK_COOKIE);
3083                     boolean isComeBack = data
3084                             .getBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_IS_COME_BACK_REQUEST);
3085                     waitForResponse = initiateBootstrappingRequestLocal(mCurrentTransactionId,
3086                             clientId, sessionId, peerId, method, cookie, isComeBack);
3087                     break;
3088                 }
3089                 case COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST: {
3090                     int clientId = msg.arg2;
3091                     Bundle data = msg.getData();
3092                     int sessionId = data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3093                     int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID);
3094                     boolean accept = data.getBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_ACCEPT);
3095                     int bootstrappingId = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_REQUEST_ID);
3096                     int method = data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD);
3097                     waitForResponse = respondToBootstrappingRequestLocal(mCurrentTransactionId,
3098                             clientId, sessionId, peerId, bootstrappingId, accept, method);
3099                     break;
3100                 }
3101                 case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: {
3102                     if (mSendQueueBlocked || mHostQueuedSendMessages.size() == 0) {
3103                         if (mVdbg) {
3104                             Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - blocked or "
3105                                     + "empty host queue");
3106                         }
3107                         waitForResponse = false;
3108                     } else {
3109                         if (mVdbg) {
3110                             Log.v(TAG, "processCommand: SEND_TOP_OF_QUEUE_MESSAGE - "
3111                                     + "sendArrivalSequenceCounter="
3112                                     + mHostQueuedSendMessages.keyAt(0));
3113                         }
3114                         Message sendMessage = mHostQueuedSendMessages.valueAt(0);
3115                         mHostQueuedSendMessages.removeAt(0);
3116 
3117                         Bundle data = sendMessage.getData();
3118                         int clientId = sendMessage.arg2;
3119                         int sessionId = sendMessage.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3120                         int peerId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_PEER_ID);
3121                         byte[] message = data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE);
3122                         int messageId = data.getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID);
3123 
3124                         msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_SENT_MESSAGE, sendMessage);
3125 
3126                         waitForResponse = sendFollowonMessageLocal(mCurrentTransactionId, clientId,
3127                                 sessionId, peerId, message, messageId);
3128                     }
3129                     break;
3130                 }
3131                 case COMMAND_TYPE_ENABLE_USAGE:
3132                     enableUsageLocal();
3133                     waitForResponse = false;
3134                     break;
3135                 case COMMAND_TYPE_DISABLE_USAGE:
3136                     disableUsageLocal(mCurrentTransactionId, msg.arg2 == 1);
3137                     waitForResponse = false;
3138                     break;
3139                 case COMMAND_TYPE_GET_CAPABILITIES:
3140                     if (mCapabilities == null) {
3141                         waitForResponse = mWifiAwareNativeApi.getCapabilities(
3142                                 mCurrentTransactionId);
3143                     } else {
3144                         if (mVdbg) {
3145                             Log.v(TAG, "COMMAND_TYPE_GET_CAPABILITIES: already have capabilities - "
3146                                     + "skipping");
3147                         }
3148                         waitForResponse = false;
3149                     }
3150                     break;
3151                 case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES:
3152                     mDataPathMgr.deleteAllInterfaces();
3153                     waitForResponse = false;
3154                     break;
3155                 case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE:
3156                     waitForResponse = mWifiAwareNativeApi.createAwareNetworkInterface(
3157                             mCurrentTransactionId, (String) msg.obj);
3158                     break;
3159                 case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE:
3160                     waitForResponse = mWifiAwareNativeApi.deleteAwareNetworkInterface(
3161                             mCurrentTransactionId, (String) msg.obj);
3162                     break;
3163                 case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP: {
3164                     Bundle data = msg.getData();
3165 
3166                     WifiAwareNetworkSpecifier networkSpecifier =
3167                             (WifiAwareNetworkSpecifier) msg.obj;
3168 
3169                     int peerId = data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID);
3170                     int channelRequestType = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE);
3171                     int channel = data.getInt(MESSAGE_BUNDLE_KEY_CHANNEL);
3172                     byte[] peer = data.getByteArray(MESSAGE_BUNDLE_KEY_MAC_ADDRESS);
3173                     String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME);
3174                     boolean isOutOfBand = data.getBoolean(MESSAGE_BUNDLE_KEY_OOB);
3175                     byte[] appInfo = data.getByteArray(MESSAGE_BUNDLE_KEY_APP_INFO);
3176 
3177                     waitForResponse = initiateDataPathSetupLocal(mCurrentTransactionId,
3178                             networkSpecifier, peerId, channelRequestType, channel, peer,
3179                             interfaceName, isOutOfBand, appInfo);
3180                     break;
3181                 }
3182                 case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST: {
3183                     Bundle data = msg.getData();
3184 
3185                     int ndpId = msg.arg2;
3186                     WifiAwareNetworkSpecifier specifier =
3187                             (WifiAwareNetworkSpecifier) msg.obj;
3188                     boolean accept = data.getBoolean(MESSAGE_BUNDLE_KEY_ACCEPT_STATE);
3189                     String interfaceName = data.getString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME);
3190                     byte[] appInfo = data.getByteArray(MESSAGE_BUNDLE_KEY_APP_INFO);
3191                     boolean isOutOfBand = data.getBoolean(MESSAGE_BUNDLE_KEY_OOB);
3192 
3193                     waitForResponse = respondToDataPathRequestLocal(mCurrentTransactionId, accept,
3194                             ndpId, interfaceName, appInfo, isOutOfBand, specifier);
3195 
3196                     break;
3197                 }
3198                 case COMMAND_TYPE_END_DATA_PATH: {
3199                     int ndpId = msg.arg2;
3200                     WakeupMessage timeout = mDataPathConfirmTimeoutMessages.get(ndpId);
3201                     if (timeout != null) {
3202                         mDataPathConfirmTimeoutMessages.remove(ndpId);
3203                         timeout.cancel();
3204                     }
3205                     waitForResponse = endDataPathLocal(mCurrentTransactionId, ndpId);
3206                     break;
3207                 }
3208                 case COMMAND_TYPE_END_PAIRING: {
3209                     int pairId = msg.arg2;
3210                     WakeupMessage timeout = mPairingConfirmTimeoutMessages.get(pairId);
3211                     if (timeout != null) {
3212                         mPairingConfirmTimeoutMessages.remove(pairId);
3213                         timeout.cancel();
3214                     }
3215                     waitForResponse = endPairingLocal(mCurrentTransactionId, pairId);
3216                     break;
3217                 }
3218                 case COMMAND_TYPE_DELAYED_INITIALIZATION:
3219                     if (SdkLevel.isAtLeastT()) {
3220                         mWifiManager.registerActiveCountryCodeChangedCallback(
3221                                 new HandlerExecutor(mHandler), new CountryCodeChangeCallback());
3222                     }
3223                     mWifiAwareNativeManager.start(getHandler());
3224                     waitForResponse = false;
3225                     break;
3226                 case COMMAND_TYPE_GET_AWARE:
3227                     WorkSource requestorWs = (WorkSource) msg.obj;
3228                     mWifiAwareNativeManager.tryToGetAware(requestorWs);
3229                     waitForResponse = false;
3230                     break;
3231                 case COMMAND_TYPE_RELEASE_AWARE:
3232                     mWifiAwareNativeManager.releaseAware();
3233                     waitForResponse = false;
3234                     break;
3235                 case COMMAND_TYPE_SUSPEND_SESSION: {
3236                     int clientId = msg.arg2;
3237                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3238 
3239                     waitForResponse = suspendSessionLocal(mCurrentTransactionId, clientId,
3240                         sessionId);
3241                     break;
3242                 }
3243                 case COMMAND_TYPE_RESUME_SESSION: {
3244                     int clientId = msg.arg2;
3245                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
3246 
3247                     waitForResponse = resumeSessionLocal(mCurrentTransactionId, clientId,
3248                         sessionId);
3249                     break;
3250                 }
3251                 default:
3252                     waitForResponse = false;
3253                     Log.wtf(TAG, "processCommand: this isn't a COMMAND -- msg=" + msg);
3254                     /* fall-through */
3255             }
3256 
3257             if (!waitForResponse) {
3258                 mCurrentTransactionId = TRANSACTION_ID_IGNORE;
3259             } else {
3260                 mCurrentCommand = obtainMessage(msg.what);
3261                 mCurrentCommand.copyFrom(msg);
3262             }
3263 
3264             return waitForResponse;
3265         }
3266 
processResponse(Message msg)3267         private void processResponse(Message msg) {
3268             if (mVdbg) {
3269                 Log.v(TAG, "processResponse: msg=" + msg);
3270             }
3271 
3272             if (mCurrentCommand == null) {
3273                 Log.wtf(TAG, "processResponse: no existing command stored!? msg=" + msg);
3274                 mCurrentTransactionId = TRANSACTION_ID_IGNORE;
3275                 return;
3276             }
3277             int reason = NanStatusCode.SUCCESS;
3278 
3279             switch (msg.arg1) {
3280                 case RESPONSE_TYPE_ON_CONFIG_SUCCESS:
3281                     onConfigCompletedLocal(mCurrentCommand);
3282                     break;
3283                 case RESPONSE_TYPE_ON_CONFIG_FAIL: {
3284                     reason = (Integer) msg.obj;
3285 
3286                     onConfigFailedLocal(mCurrentCommand, reason);
3287                     break;
3288                 }
3289                 case RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS: {
3290                     byte pubSubId = (Byte) msg.obj;
3291                     boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE);
3292 
3293                     onSessionConfigSuccessLocal(mCurrentCommand, pubSubId, isPublish);
3294                     break;
3295                 }
3296                 case RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL: {
3297                     reason = (int) msg.obj;
3298                     boolean isPublish = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SESSION_TYPE);
3299 
3300                     onSessionConfigFailLocal(mCurrentCommand, isPublish, reason);
3301                     break;
3302                 }
3303                 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS: {
3304                     Message sentMessage = mCurrentCommand.getData().getParcelable(
3305                             MESSAGE_BUNDLE_KEY_SENT_MESSAGE);
3306                     sentMessage.getData().putLong(MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME,
3307                             SystemClock.elapsedRealtime());
3308                     mFwQueuedSendMessages.put(mCurrentTransactionId, sentMessage);
3309                     updateSendMessageTimeout();
3310                     if (!mSendQueueBlocked) {
3311                         transmitNextMessage();
3312                     }
3313 
3314                     if (mVdbg) {
3315                         Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_SUCCESS - arrivalSeq="
3316                                 + sentMessage.getData().getInt(
3317                                 MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ));
3318                     }
3319                     break;
3320                 }
3321                 case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL: {
3322                     if (mVdbg) {
3323                         Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - blocking!");
3324                     }
3325                     reason = (int) msg.obj;
3326                     Message sentMessage = mCurrentCommand.getData().getParcelable(
3327                             MESSAGE_BUNDLE_KEY_SENT_MESSAGE);
3328                     if (reason == NanStatusCode.FOLLOWUP_TX_QUEUE_FULL) {
3329                         int arrivalSeq = sentMessage.getData().getInt(
3330                                 MESSAGE_BUNDLE_KEY_MESSAGE_ARRIVAL_SEQ);
3331                         mHostQueuedSendMessages.put(arrivalSeq, sentMessage);
3332                         mSendQueueBlocked = true;
3333 
3334                         if (mVdbg) {
3335                             Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - arrivalSeq="
3336                                     + arrivalSeq + " -- blocking");
3337                         }
3338                     } else {
3339                         onMessageSendFailLocal(sentMessage, NanStatusCode.INTERNAL_FAILURE);
3340                         if (!mSendQueueBlocked) {
3341                             transmitNextMessage();
3342                         }
3343                     }
3344                     break;
3345                 }
3346                 case RESPONSE_TYPE_ON_CAPABILITIES_UPDATED: {
3347                     onCapabilitiesUpdatedResponseLocal((Capabilities) msg.obj);
3348                     break;
3349                 }
3350                 case RESPONSE_TYPE_ON_CREATE_INTERFACE:
3351                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3352                     onCreateDataPathInterfaceResponseLocal(mCurrentCommand,
3353                             msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG),
3354                             reason);
3355                     break;
3356                 case RESPONSE_TYPE_ON_DELETE_INTERFACE:
3357                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3358                     onDeleteDataPathInterfaceResponseLocal(mCurrentCommand,
3359                             msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG),
3360                             reason);
3361                     break;
3362                 case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS: {
3363                     int ndpId = (int) msg.obj;
3364                     boolean success = onInitiateDataPathResponseSuccessLocal(mCurrentCommand,
3365                             ndpId);
3366                     if (success) {
3367                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
3368                                 HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT,
3369                                 ndpId);
3370                         mDataPathConfirmTimeoutMessages.put(ndpId, timeout);
3371                         timeout.schedule(
3372                                 SystemClock.elapsedRealtime() + AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT);
3373                         sendAwareResourcesChangedBroadcast();
3374                     }
3375                     break;
3376                 }
3377                 case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL:
3378                     reason = (int) msg.obj;
3379                     onInitiateDataPathResponseFailLocal(mCurrentCommand, reason);
3380                     break;
3381                 case RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST: {
3382                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3383                     boolean success = onRespondToDataPathSetupRequestResponseLocal(mCurrentCommand,
3384                             msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG),
3385                             reason);
3386                     if (success) {
3387                         int ndpId = mCurrentCommand.arg2;
3388                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
3389                                 HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT,
3390                                 ndpId);
3391                         mDataPathConfirmTimeoutMessages.put(ndpId, timeout);
3392                         timeout.schedule(
3393                                 SystemClock.elapsedRealtime() + AWARE_WAIT_FOR_DP_CONFIRM_TIMEOUT);
3394                     }
3395                     break;
3396                 }
3397                 case RESPONSE_TYPE_ON_END_DATA_PATH:
3398                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3399                     onEndPathEndResponseLocal(mCurrentCommand,
3400                             msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG),
3401                             reason);
3402                     break;
3403                 case RESPONSE_TYPE_ON_END_PAIRING:
3404                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3405                     onPairingEndResponseLocal(mCurrentCommand,
3406                             msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), reason);
3407                     break;
3408                 case RESPONSE_TYPE_ON_DISABLE:
3409                     reason = (int) msg.obj;
3410                     onDisableResponseLocal(mCurrentCommand, reason);
3411                     break;
3412                 case RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS: {
3413                     int pairingId = (int) msg.obj;
3414                     boolean success = onInitiatePairingResponseSuccessLocal(mCurrentCommand,
3415                             pairingId);
3416                     if (success) {
3417                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
3418                                 HAL_PAIRING_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_PAIRING_TIMEOUT,
3419                                 pairingId, msg.getData().getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE));
3420                         mPairingConfirmTimeoutMessages.put(pairingId, timeout);
3421                         timeout.schedule(SystemClock.elapsedRealtime()
3422                                 + AWARE_WAIT_FOR_PAIRING_CONFIRM_TIMEOUT);
3423                     }
3424                     break;
3425                 }
3426                 case RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL: {
3427                     reason = (int) msg.obj;
3428                     onInitiatePairingResponseFailLocal(mCurrentCommand, reason);
3429                     break;
3430                 }
3431                 case RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS: {
3432                     boolean success = onRespondToPairingIndicationResponseSuccessLocal(
3433                             mCurrentCommand);
3434                     if (success) {
3435                         int pairingId = mCurrentCommand.getData()
3436                                 .getInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID);
3437                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
3438                                 HAL_PAIRING_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_PAIRING_TIMEOUT,
3439                                 pairingId, msg.getData().getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE));
3440                         mPairingConfirmTimeoutMessages.put(pairingId, timeout);
3441                         timeout.schedule(SystemClock.elapsedRealtime()
3442                                 + AWARE_WAIT_FOR_PAIRING_CONFIRM_TIMEOUT);
3443                     }
3444                     break;
3445                 }
3446                 case RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL: {
3447                     reason = (int) msg.obj;
3448                     onRespondToPairingIndicationResponseFail(mCurrentCommand, reason);
3449                     break;
3450                 }
3451                 case RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS: {
3452                     int bootstrappingId = (int) msg.obj;
3453                     boolean success = onInitiateBootstrappingResponseSuccessLocal(mCurrentCommand,
3454                             bootstrappingId);
3455 
3456                     if (success) {
3457                         WakeupMessage timeout = new WakeupMessage(mContext, getHandler(),
3458                                 HAL_PAIRING_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT,
3459                                 bootstrappingId, 0, mCurrentCommand);
3460                         mBootstrappingConfirmTimeoutMessages.put(bootstrappingId, timeout);
3461                         timeout.schedule(SystemClock.elapsedRealtime()
3462                                 + AWARE_WAIT_FOR_PAIRING_CONFIRM_TIMEOUT);
3463                     }
3464                     break;
3465                 }
3466                 case RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL: {
3467                     reason = (int) msg.obj;
3468                     onInitiateBootStrappingResponseFailLocal(mCurrentCommand, reason);
3469                     break;
3470                 }
3471                 case RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS: {
3472                     onRespondToBootStrappingRequestSuccessLocal(mCurrentCommand);
3473                     break;
3474                 }
3475                 case RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL: {
3476                     reason = (int) msg.obj;
3477                     Log.e(TAG, "RespondToBootstrappingIndication failed, reason: " + reason);
3478                     break;
3479                 }
3480                 case RESPONSE_TYPE_ON_SUSPEND: {
3481                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3482                     boolean success = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG);
3483                     onSuspendResponseLocal(mCurrentCommand, success, reason);
3484                     break;
3485                 }
3486                 case RESPONSE_TYPE_ON_RESUME: {
3487                     reason = msg.getData().getInt(MESSAGE_BUNDLE_KEY_STATUS_CODE);
3488                     boolean success = msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG);
3489                     onResumeResponseLocal(mCurrentCommand, success, reason);
3490                     break;
3491                 }
3492                 default:
3493                     Log.wtf(TAG, "processResponse: this isn't a RESPONSE -- msg=" + msg);
3494                     mCurrentCommand = null;
3495                     mCurrentTransactionId = TRANSACTION_ID_IGNORE;
3496                     return;
3497             }
3498             if (msg.arg1 != RESPONSE_TYPE_ON_CONFIG_SUCCESS
3499                     && msg.arg1 != RESPONSE_TYPE_ON_CONFIG_FAIL) {
3500                 // Config response handle separately to identify it's connect or reconfigure
3501                 recordHalApiCall(mCurrentCommand.arg1, reason, mStartTime);
3502             }
3503 
3504             mCurrentCommand = null;
3505             mCurrentTransactionId = TRANSACTION_ID_IGNORE;
3506         }
3507 
processTimeout(Message msg)3508         private void processTimeout(Message msg) {
3509             if (mVerboseLoggingEnabled) {
3510                 Log.v(TAG, "processTimeout: msg=" + msg);
3511             }
3512 
3513             if (mCurrentCommand == null) {
3514                 Log.wtf(TAG, "processTimeout: no existing command stored!? msg=" + msg);
3515                 mCurrentTransactionId = TRANSACTION_ID_IGNORE;
3516                 return;
3517             }
3518 
3519             /*
3520              * Only have to handle those COMMANDs which wait for a response.
3521              */
3522             switch (msg.arg1) {
3523                 case COMMAND_TYPE_CONNECT:
3524                 case COMMAND_TYPE_DISCONNECT:
3525 
3526                 case COMMAND_TYPE_RECONFIGURE:
3527                     /*
3528                      * Reconfigure timed-out. There is nothing to do but log the issue - which
3529                       * will be done in the callback.
3530                      */
3531                     onConfigFailedLocal(mCurrentCommand, NanStatusCode.INTERNAL_FAILURE);
3532                     break;
3533                 case COMMAND_TYPE_TERMINATE_SESSION: {
3534                     Log.wtf(TAG, "processTimeout: TERMINATE_SESSION - shouldn't be waiting!");
3535                     break;
3536                 }
3537                 case COMMAND_TYPE_PUBLISH:
3538                 case COMMAND_TYPE_UPDATE_PUBLISH: {
3539                     onSessionConfigFailLocal(mCurrentCommand, true, NanStatusCode.INTERNAL_FAILURE);
3540                     break;
3541                 }
3542                 case COMMAND_TYPE_SUBSCRIBE:
3543                 case COMMAND_TYPE_UPDATE_SUBSCRIBE: {
3544                     onSessionConfigFailLocal(mCurrentCommand, false,
3545                             NanStatusCode.INTERNAL_FAILURE);
3546                     break;
3547                 }
3548                 case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: {
3549                     Log.wtf(TAG, "processTimeout: ENQUEUE_SEND_MESSAGE - shouldn't be waiting!");
3550                     break;
3551                 }
3552                 case COMMAND_TYPE_INITIATE_PAIRING_REQUEST: {
3553                     onInitiatePairingResponseFailLocal(mCurrentCommand,
3554                             NanStatusCode.INTERNAL_FAILURE);
3555                     break;
3556                 }
3557                 case COMMAND_TYPE_RESPONSE_PAIRING_REQUEST: {
3558                     onRespondToPairingIndicationResponseFail(mCurrentCommand,
3559                             NanStatusCode.INTERNAL_FAILURE);
3560                     break;
3561                 }
3562                 case COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST: {
3563                     onInitiateBootStrappingResponseFailLocal(mCurrentCommand,
3564                             NanStatusCode.INTERNAL_FAILURE);
3565                     break;
3566                 }
3567                 case COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST: {
3568                     break;
3569                 }
3570                 case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: {
3571                     Message sentMessage = mCurrentCommand.getData().getParcelable(
3572                             MESSAGE_BUNDLE_KEY_SENT_MESSAGE);
3573                     onMessageSendFailLocal(sentMessage, NanStatusCode.INTERNAL_FAILURE);
3574                     mSendQueueBlocked = false;
3575                     transmitNextMessage();
3576                     break;
3577                 }
3578                 case COMMAND_TYPE_ENABLE_USAGE:
3579                     Log.wtf(TAG, "processTimeout: ENABLE_USAGE - shouldn't be waiting!");
3580                     break;
3581                 case COMMAND_TYPE_DISABLE_USAGE:
3582                     Log.wtf(TAG, "processTimeout: DISABLE_USAGE - shouldn't be waiting!");
3583                     break;
3584                 case COMMAND_TYPE_GET_CAPABILITIES:
3585                     Log.e(TAG,
3586                             "processTimeout: GET_CAPABILITIES timed-out - strange, will try again"
3587                                     + " when next enabled!?");
3588                     break;
3589                 case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES:
3590                     Log.wtf(TAG,
3591                             "processTimeout: DELETE_ALL_DATA_PATH_INTERFACES - shouldn't be "
3592                                     + "waiting!");
3593                     break;
3594                 case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE:
3595                     // TODO: fix status: timeout
3596                     onCreateDataPathInterfaceResponseLocal(mCurrentCommand, false, 0);
3597                     break;
3598                 case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE:
3599                     // TODO: fix status: timeout
3600                     onDeleteDataPathInterfaceResponseLocal(mCurrentCommand, false, 0);
3601                     break;
3602                 case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP:
3603                     // TODO: fix status: timeout
3604                     onInitiateDataPathResponseFailLocal(mCurrentCommand, 0);
3605                     break;
3606                 case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST:
3607                     // TODO: fix status: timeout
3608                     onRespondToDataPathSetupRequestResponseLocal(mCurrentCommand, false, 0);
3609                     break;
3610                 case COMMAND_TYPE_END_DATA_PATH:
3611                     // TODO: fix status: timeout
3612                     onEndPathEndResponseLocal(mCurrentCommand, false, 0);
3613                     break;
3614                 case COMMAND_TYPE_END_PAIRING:
3615                     // TODO: fix status: timeout
3616                     break;
3617                 case COMMAND_TYPE_DELAYED_INITIALIZATION:
3618                     Log.wtf(TAG,
3619                             "processTimeout: COMMAND_TYPE_DELAYED_INITIALIZATION - shouldn't be "
3620                                     + "waiting!");
3621                     break;
3622                 case COMMAND_TYPE_GET_AWARE:
3623                     Log.wtf(TAG,
3624                             "processTimeout: COMMAND_TYPE_GET_AWARE - shouldn't be waiting!");
3625                     break;
3626                 case COMMAND_TYPE_RELEASE_AWARE:
3627                     Log.wtf(TAG,
3628                             "processTimeout: COMMAND_TYPE_RELEASE_AWARE - shouldn't be waiting!");
3629                     break;
3630                 case COMMAND_TYPE_DISABLE:
3631                     onDisableResponseLocal(mCurrentCommand, NanStatusCode.INTERNAL_FAILURE);
3632                     break;
3633                 default:
3634                     Log.wtf(TAG, "processTimeout: this isn't a COMMAND -- msg=" + msg);
3635                     /* fall-through */
3636             }
3637 
3638             mCurrentCommand = null;
3639             mCurrentTransactionId = TRANSACTION_ID_IGNORE;
3640         }
3641 
updateSendMessageTimeout()3642         private void updateSendMessageTimeout() {
3643             if (mVdbg) {
3644                 Log.v(TAG, "updateSendMessageTimeout: mHostQueuedSendMessages.size()="
3645                         + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()="
3646                         + mFwQueuedSendMessages.size() + ", mSendQueueBlocked="
3647                         + mSendQueueBlocked);
3648             }
3649             Iterator<Message> it = mFwQueuedSendMessages.values().iterator();
3650             if (it.hasNext()) {
3651                 /*
3652                  * Schedule timeout based on the first message in the queue (which is the earliest
3653                  * submitted message). Timeout = queuing time + timeout constant.
3654                  */
3655                 Message msg = it.next();
3656                 mSendMessageTimeoutMessage.schedule(
3657                         msg.getData().getLong(MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME)
3658                         + AWARE_SEND_MESSAGE_TIMEOUT);
3659             } else {
3660                 mSendMessageTimeoutMessage.cancel();
3661             }
3662         }
3663 
processSendMessageTimeout()3664         private void processSendMessageTimeout() {
3665             if (mVdbg) {
3666                 Log.v(TAG, "processSendMessageTimeout: mHostQueuedSendMessages.size()="
3667                         + mHostQueuedSendMessages.size() + ", mFwQueuedSendMessages.size()="
3668                         + mFwQueuedSendMessages.size() + ", mSendQueueBlocked="
3669                         + mSendQueueBlocked);
3670             }
3671 
3672             /*
3673              * Note: using 'first' to always time-out (remove) at least 1 notification (partially)
3674              * due to test code needs: there's no way to mock elapsedRealtime(). TODO: replace with
3675              * injected getClock() once moved off of mmwd.
3676              */
3677             boolean first = true;
3678             long currentTime = SystemClock.elapsedRealtime();
3679             Iterator<Map.Entry<Short, Message>> it = mFwQueuedSendMessages.entrySet().iterator();
3680             while (it.hasNext()) {
3681                 Map.Entry<Short, Message> entry = it.next();
3682                 short transactionId = entry.getKey();
3683                 Message message = entry.getValue();
3684                 long messageEnqueueTime = message.getData().getLong(
3685                         MESSAGE_BUNDLE_KEY_SEND_MESSAGE_ENQUEUE_TIME);
3686                 if (first || messageEnqueueTime + AWARE_SEND_MESSAGE_TIMEOUT <= currentTime) {
3687                     if (mVerboseLoggingEnabled) {
3688                         Log.v(TAG, "processSendMessageTimeout: expiring - transactionId="
3689                                 + transactionId + ", message=" + message
3690                                 + ", due to messageEnqueueTime=" + messageEnqueueTime
3691                                 + ", currentTime=" + currentTime);
3692                     }
3693                     onMessageSendFailLocal(message, NanStatusCode.INTERNAL_FAILURE);
3694                     it.remove();
3695                     first = false;
3696                 } else {
3697                     break;
3698                 }
3699             }
3700             updateSendMessageTimeout();
3701             mSendQueueBlocked = false;
3702             transmitNextMessage();
3703         }
3704 
isUidExceededMessageQueueDepthLimit(int uid)3705         private boolean isUidExceededMessageQueueDepthLimit(int uid) {
3706             int size = mHostQueuedSendMessages.size();
3707             int numOfMessages = 0;
3708             if (size < MESSAGE_QUEUE_DEPTH_PER_UID) {
3709                 return false;
3710             }
3711             for (int i = 0; i < size; ++i) {
3712                 if (mHostQueuedSendMessages.valueAt(i).getData()
3713                         .getInt(MESSAGE_BUNDLE_KEY_UID) == uid) {
3714                     numOfMessages++;
3715                     if (numOfMessages >= MESSAGE_QUEUE_DEPTH_PER_UID) {
3716                         return true;
3717                     }
3718                 }
3719             }
3720             return false;
3721         }
3722 
3723         @Override
getLogRecString(Message msg)3724         protected String getLogRecString(Message msg) {
3725             StringBuilder sb = new StringBuilder(messageToString(msg));
3726 
3727             if (msg.what == MESSAGE_TYPE_COMMAND
3728                     && mCurrentTransactionId != TRANSACTION_ID_IGNORE) {
3729                 sb.append(" (Transaction ID=").append(mCurrentTransactionId).append(")");
3730             }
3731 
3732             return sb.toString();
3733         }
3734 
3735         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)3736         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3737             pw.println("WifiAwareStateMachine:");
3738             pw.println("  mNextTransactionId: " + mNextTransactionId);
3739             pw.println("  mNextSessionId: " + mNextSessionId);
3740             pw.println("  mCurrentCommand: " + mCurrentCommand);
3741             pw.println("  mCurrentTransaction: " + mCurrentTransactionId);
3742             pw.println("  mSendQueueBlocked: " + mSendQueueBlocked);
3743             pw.println("  mSendArrivalSequenceCounter: " + mSendArrivalSequenceCounter);
3744             pw.println("  mHostQueuedSendMessages: [" + mHostQueuedSendMessages + "]");
3745             pw.println("  mFwQueuedSendMessages: [" + mFwQueuedSendMessages + "]");
3746             super.dump(fd, pw, args);
3747         }
3748     }
3749 
sendAwareStateChangedBroadcast(boolean enabled)3750     private void sendAwareStateChangedBroadcast(boolean enabled) {
3751         if (mVdbg) {
3752             Log.v(TAG, "sendAwareStateChangedBroadcast: enabled=" + enabled);
3753         }
3754         final Intent intent = new Intent(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED);
3755         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3756         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
3757     }
3758 
sendAwareResourcesChangedBroadcast()3759     private void sendAwareResourcesChangedBroadcast() {
3760         if (!SdkLevel.isAtLeastT()) {
3761             return;
3762         }
3763         if (mVdbg) {
3764             Log.v(TAG, "sendAwareResourcesChangedBroadcast");
3765         }
3766         final Intent intent = new Intent(WifiAwareManager.ACTION_WIFI_AWARE_RESOURCE_CHANGED);
3767         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3768         intent.putExtra(WifiAwareManager.EXTRA_AWARE_RESOURCES, getAvailableAwareResources());
3769         mContext.sendBroadcastAsUser(intent, UserHandle.ALL, ACCESS_WIFI_STATE);
3770     }
3771 
3772     /*
3773      * COMMANDS
3774      */
3775 
connectLocal(short transactionId, int clientId, int uid, int pid, String callingPackage, @Nullable String callingFeatureId, IWifiAwareEventCallback callback, ConfigRequest configRequest, boolean notifyIdentityChange, Object attributionSource, boolean awareOffload, boolean reEnableAware, int callerType)3776     private boolean connectLocal(short transactionId, int clientId, int uid, int pid,
3777             String callingPackage, @Nullable String callingFeatureId,
3778             IWifiAwareEventCallback callback, ConfigRequest configRequest,
3779             boolean notifyIdentityChange, Object attributionSource, boolean awareOffload,
3780             boolean reEnableAware, int callerType) {
3781         if (mVerboseLoggingEnabled) {
3782             Log.v(TAG,
3783                     "connectLocal(): transactionId=" + transactionId + ", clientId=" + clientId
3784                             + ", uid=" + uid + ", pid=" + pid + ", callingPackage=" + callingPackage
3785                             + ", callback=" + callback + ", configRequest=" + configRequest
3786                             + ", notifyIdentityChange=" + notifyIdentityChange
3787                             + ", awareOffload" + awareOffload
3788                             + ", reEnableAware" + reEnableAware);
3789         }
3790         if (!mUsageEnabled) {
3791             Log.w(TAG, "connect(): called with mUsageEnabled=false");
3792             try {
3793                 callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE);
3794                 mAwareMetrics.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE, callerType,
3795                         callingFeatureId, uid);
3796             } catch (RemoteException e) {
3797                 Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e);
3798             }
3799             return false;
3800         }
3801 
3802         if (mClients.get(clientId) != null) {
3803             Log.e(TAG, "connectLocal: entry already exists for clientId=" + clientId);
3804         }
3805 
3806         if (mVdbg) {
3807             Log.v(TAG, "mCurrentAwareConfiguration=" + mCurrentAwareConfiguration
3808                     + ", mCurrentIdentityNotification=" + mCurrentIdentityNotification);
3809         }
3810 
3811         ConfigRequest merged = mergeConfigRequests(configRequest);
3812         if (merged == null) {
3813             Log.e(TAG, "connectLocal: requested configRequest=" + configRequest
3814                     + ", incompatible with current configurations");
3815             try {
3816                 callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE);
3817                 mAwareMetrics.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE, callerType,
3818                         callingFeatureId, uid);
3819             } catch (RemoteException e) {
3820                 Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e);
3821             }
3822             return false;
3823         } else if (mVdbg) {
3824             Log.v(TAG, "connectLocal: merged=" + merged);
3825         }
3826 
3827         if (mCurrentAwareConfiguration != null && mCurrentAwareConfiguration.equals(merged)
3828                 && (mCurrentIdentityNotification || !notifyIdentityChange)
3829                 && !reEnableAware) {
3830             if (awareOffload && !isAwareOffloading()) {
3831                 try {
3832                     if (mVdbg) {
3833                         Log.v(TAG, "Connect failure for clientId:" + clientId);
3834                     }
3835                     callback.onConnectFail(clientId);
3836                 } catch (RemoteException e) {
3837                     Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e);
3838                 }
3839                 return false;
3840             }
3841             WifiAwareClientState client = new WifiAwareClientState(mContext, clientId, uid, pid,
3842                     callingPackage, callingFeatureId, callback, configRequest, notifyIdentityChange,
3843                     SystemClock.elapsedRealtime(), mWifiPermissionsUtil, attributionSource,
3844                     awareOffload, callerType);
3845             client.enableVerboseLogging(mVerboseLoggingEnabled, mVdbg);
3846             client.onClusterChange(mClusterEventType, mClusterId, mCurrentDiscoveryInterfaceMac);
3847             mClients.append(clientId, client);
3848             mAwareMetrics.recordAttachSession(uid, notifyIdentityChange, mClients, callerType,
3849                     callingFeatureId);
3850             try {
3851                 if (mVdbg) {
3852                     Log.v(TAG, "Connect success for clientId:" + clientId);
3853                 }
3854                 callback.onConnectSuccess(clientId);
3855             } catch (RemoteException e) {
3856                 Log.w(TAG, "connectLocal onConnectSuccess(): RemoteException (FYI): " + e);
3857             }
3858             if (!mWifiAwareNativeManager.replaceRequestorWs(createMergedRequestorWs())) {
3859                 Log.w(TAG, "Failed to replace requestorWs");
3860             }
3861             return false;
3862         }
3863         boolean notificationRequired =
3864                 doesAnyClientNeedIdentityChangeNotifications() || notifyIdentityChange;
3865         boolean rangingRequired = doesAnyClientNeedRanging();
3866         int instantMode = getInstantModeFromAllClients();
3867         boolean enableInstantMode = false;
3868         int instantModeChannel = 0;
3869         if (instantMode != INSTANT_MODE_DISABLED || mInstantCommModeGlobalEnable) {
3870             enableInstantMode = true;
3871             instantModeChannel = getAwareInstantCommunicationChannel(instantMode);
3872         }
3873 
3874         if (mCurrentAwareConfiguration == null) {
3875             WorkSource workSource;
3876             if (awareOffload || mOpportunisticSet.contains(callingPackage)) {
3877                 workSource = new WorkSource(Process.WIFI_UID);
3878             } else {
3879                 workSource = new WorkSource(uid, callingPackage);
3880             }
3881             mWifiAwareNativeManager.tryToGetAware(workSource);
3882         }
3883         boolean initialConfiguration = mCurrentAwareConfiguration == null
3884                 || reEnableAware;
3885         boolean success = mWifiAwareNativeApi.enableAndConfigure(transactionId, merged,
3886                 notificationRequired, initialConfiguration,
3887                 mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode(),
3888                 rangingRequired, enableInstantMode, instantModeChannel, mClusterIdInt);
3889         if (!success) {
3890             if (mCurrentAwareConfiguration == null) {
3891                 mWifiAwareNativeManager.releaseAware();
3892             }
3893             try {
3894                 callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE);
3895                 mAwareMetrics.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE, callerType,
3896                         callingFeatureId, uid);
3897             } catch (RemoteException e) {
3898                 Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI):  " + e);
3899             }
3900         }
3901 
3902         return success;
3903     }
3904 
disconnectLocal(short transactionId, int clientId)3905     private boolean disconnectLocal(short transactionId, int clientId) {
3906         if (mVerboseLoggingEnabled) {
3907             Log.v(TAG, "disconnectLocal(): transactionId=" + transactionId
3908                     + ", clientId=" + clientId);
3909         }
3910 
3911         WifiAwareClientState client = mClients.get(clientId);
3912         if (client == null) {
3913             Log.e(TAG, "disconnectLocal: no entry for clientId=" + clientId);
3914             return false;
3915         }
3916         mClients.delete(clientId);
3917         mAwareMetrics.recordAttachSessionDuration(client.getCreationTime());
3918         SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions();
3919         for (int i = 0; i < sessions.size(); ++i) {
3920             mAwareMetrics.recordDiscoverySessionDuration(sessions.valueAt(i).getCreationTime(),
3921                     sessions.valueAt(i).isPublishSession(), sessions.valueAt(i).getSessionId());
3922         }
3923         client.destroy();
3924 
3925         if (mClients.size() == 0) {
3926             mCurrentAwareConfiguration = null;
3927             mPairingRequest.clear();
3928             mDataPathMgr.deleteAllInterfaces();
3929             mCurrentRangingEnabled = false;
3930             mCurrentIdentityNotification = false;
3931             mInstantCommModeClientRequest = INSTANT_MODE_DISABLED;
3932             mAwareMetrics.reportAwareInstantModeEnabled(false);
3933             mSm.onAwareDownCleanupSendQueueState();
3934             deferDisableAware(true);
3935             return false;
3936         }
3937 
3938         if (!mWifiAwareNativeManager.replaceRequestorWs(createMergedRequestorWs())) {
3939             Log.w(TAG, "Failed to replace requestorWs");
3940         }
3941 
3942         ConfigRequest merged = mergeConfigRequests(null);
3943         if (merged == null) {
3944             Log.wtf(TAG, "disconnectLocal: got an incompatible merge on remaining configs!?");
3945             return false;
3946         }
3947         boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications();
3948         boolean rangingEnabled = doesAnyClientNeedRanging();
3949         int instantMode = getInstantModeFromAllClients();
3950         boolean enableInstantMode = false;
3951         int instantModeChannel = 0;
3952         if (instantMode != INSTANT_MODE_DISABLED || mInstantCommModeGlobalEnable) {
3953             enableInstantMode = true;
3954             instantModeChannel = getAwareInstantCommunicationChannel(instantMode);
3955         }
3956         if (merged.equals(mCurrentAwareConfiguration)
3957                 && mCurrentIdentityNotification == notificationReqs
3958                 && mCurrentRangingEnabled == rangingEnabled
3959                 && mInstantCommModeClientRequest == instantMode) {
3960             return false;
3961         }
3962 
3963         return mWifiAwareNativeApi.enableAndConfigure(transactionId, merged, notificationReqs,
3964                 false, mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode(),
3965                 rangingEnabled, enableInstantMode, instantModeChannel, mClusterIdInt);
3966     }
3967 
reconfigureLocal(short transactionId)3968     private boolean reconfigureLocal(short transactionId) {
3969         if (mVdbg) Log.v(TAG, "reconfigureLocal(): transactionId=" + transactionId);
3970 
3971         if (mClients.size() == 0) {
3972             // no clients - Aware is not enabled, nothing to reconfigure
3973             return false;
3974         }
3975 
3976         boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications();
3977         boolean rangingEnabled = doesAnyClientNeedRanging();
3978         int instantMode = getInstantModeFromAllClients();
3979         boolean enableInstantMode = false;
3980         int instantModeChannel = 0;
3981         if (instantMode != INSTANT_MODE_DISABLED || mInstantCommModeGlobalEnable) {
3982             enableInstantMode = true;
3983             instantModeChannel = getAwareInstantCommunicationChannel(instantMode);
3984         }
3985 
3986         return mWifiAwareNativeApi.enableAndConfigure(transactionId, mergeConfigRequests(null),
3987                 notificationReqs, false, mPowerManager.isInteractive(),
3988                 mPowerManager.isDeviceIdleMode(), rangingEnabled,
3989                 enableInstantMode, instantModeChannel, mClusterIdInt);
3990     }
3991 
terminateSessionLocal(int clientId, int sessionId)3992     private void terminateSessionLocal(int clientId, int sessionId) {
3993         if (mVerboseLoggingEnabled) {
3994             Log.v(TAG, "terminateSessionLocal(): clientId=" + clientId
3995                     + ", sessionId=" + sessionId);
3996         }
3997 
3998         WifiAwareClientState client = mClients.get(clientId);
3999         if (client == null) {
4000             Log.e(TAG, "terminateSession: no client exists for clientId=" + clientId);
4001             return;
4002         }
4003 
4004         WifiAwareDiscoverySessionState session = client.terminateSession(sessionId);
4005         // If Ranging enabled or instant mode require changes, reconfigure.
4006         if (mCurrentRangingEnabled != doesAnyClientNeedRanging()
4007                 || mInstantCommModeClientRequest != getInstantModeFromAllClients()) {
4008             reconfigure();
4009         }
4010         if (session != null) {
4011             mAwareMetrics.recordDiscoverySessionDuration(session.getCreationTime(),
4012                     session.isPublishSession(), sessionId);
4013         }
4014         sendAwareResourcesChangedBroadcast();
4015     }
4016 
publishLocal(short transactionId, int clientId, PublishConfig publishConfig, IWifiAwareDiscoverySessionCallback callback)4017     private boolean publishLocal(short transactionId, int clientId, PublishConfig publishConfig,
4018             IWifiAwareDiscoverySessionCallback callback) {
4019         if (mVerboseLoggingEnabled) {
4020             Log.v(TAG, "publishLocal(): transactionId=" + transactionId + ", clientId=" + clientId
4021                     + ", publishConfig=" + publishConfig + ", callback=" + callback);
4022         }
4023 
4024         WifiAwareClientState client = mClients.get(clientId);
4025         if (client == null) {
4026             Log.e(TAG, "publishLocal: no client exists for clientId=" + clientId);
4027             try {
4028                 callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE);
4029             } catch (RemoteException e) {
4030                 Log.w(TAG, "publishLocal onSessionConfigFail(): RemoteException (FYI): " + e);
4031             }
4032             return false;
4033         }
4034         AwarePairingConfig pairingConfig = publishConfig.getPairingConfig();
4035         byte[] nik = null;
4036         if (pairingConfig != null && pairingConfig.isPairingVerificationEnabled()) {
4037             nik = mPairingConfigManager
4038                     .getNikForCallingPackage(client.getCallingPackage());
4039         }
4040         boolean success = mWifiAwareNativeApi.publish(transactionId, (byte) 0, publishConfig, nik);
4041         if (!success) {
4042             try {
4043                 callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE);
4044             } catch (RemoteException e) {
4045                 Log.w(TAG, "publishLocal onSessionConfigFail(): RemoteException (FYI): " + e);
4046             }
4047             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE,
4048                     true, client.mCallerType, client.mCallingFeatureId);
4049         }
4050 
4051         return success;
4052     }
4053 
updatePublishLocal(short transactionId, int clientId, int sessionId, PublishConfig publishConfig)4054     private boolean updatePublishLocal(short transactionId, int clientId, int sessionId,
4055             PublishConfig publishConfig) {
4056         if (mVdbg) {
4057             Log.v(TAG, "updatePublishLocal(): transactionId=" + transactionId + ", clientId="
4058                     + clientId + ", sessionId=" + sessionId + ", publishConfig=" + publishConfig);
4059         }
4060 
4061         WifiAwareClientState client = mClients.get(clientId);
4062         if (client == null) {
4063             Log.e(TAG, "updatePublishLocal: no client exists for clientId=" + clientId);
4064             return false;
4065         }
4066 
4067         WifiAwareDiscoverySessionState session = client.getSession(sessionId);
4068         if (session == null) {
4069             Log.e(TAG, "updatePublishLocal: no session exists for clientId=" + clientId
4070                     + ", sessionId=" + sessionId);
4071             return false;
4072         }
4073 
4074         AwarePairingConfig pairingConfig = publishConfig.getPairingConfig();
4075         byte[] nik = null;
4076         if (pairingConfig != null && pairingConfig.isPairingVerificationEnabled()) {
4077             nik = mPairingConfigManager.getNikForCallingPackage(
4078                     client.getCallingPackage());
4079         }
4080 
4081         boolean status = session.updatePublish(transactionId, publishConfig, nik);
4082         if (!status) {
4083             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE,
4084                     true, client.mCallerType, client.mCallingFeatureId);
4085         }
4086         return status;
4087     }
4088 
subscribeLocal(short transactionId, int clientId, SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback)4089     private boolean subscribeLocal(short transactionId, int clientId,
4090             SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback) {
4091         if (mVerboseLoggingEnabled) {
4092             Log.v(TAG, "subscribeLocal(): transactionId=" + transactionId + ", clientId=" + clientId
4093                     + ", subscribeConfig=" + subscribeConfig + ", callback=" + callback);
4094         }
4095 
4096         WifiAwareClientState client = mClients.get(clientId);
4097         if (client == null) {
4098             try {
4099                 callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE);
4100             } catch (RemoteException e) {
4101                 Log.w(TAG, "subscribeLocal onSessionConfigFail(): RemoteException (FYI): " + e);
4102             }
4103             Log.e(TAG, "subscribeLocal: no client exists for clientId=" + clientId);
4104             return false;
4105         }
4106         AwarePairingConfig pairingConfig = subscribeConfig.getPairingConfig();
4107         byte[] nik = null;
4108         if (pairingConfig != null && pairingConfig.isPairingVerificationEnabled()) {
4109             nik = mPairingConfigManager.getNikForCallingPackage(
4110                     client.getCallingPackage());
4111         }
4112 
4113         boolean success = mWifiAwareNativeApi.subscribe(transactionId, (byte) 0, subscribeConfig,
4114                 nik);
4115         if (!success) {
4116             try {
4117                 callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE);
4118             } catch (RemoteException e) {
4119                 Log.w(TAG, "subscribeLocal onSessionConfigFail(): RemoteException (FYI): " + e);
4120             }
4121             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE,
4122                     false, client.mCallerType, client.mCallingFeatureId);
4123         }
4124 
4125         return success;
4126     }
4127 
updateSubscribeLocal(short transactionId, int clientId, int sessionId, SubscribeConfig subscribeConfig)4128     private boolean updateSubscribeLocal(short transactionId, int clientId, int sessionId,
4129             SubscribeConfig subscribeConfig) {
4130         if (mVdbg) {
4131             Log.v(TAG,
4132                     "updateSubscribeLocal(): transactionId=" + transactionId + ", clientId="
4133                             + clientId + ", sessionId=" + sessionId + ", subscribeConfig="
4134                             + subscribeConfig);
4135         }
4136 
4137         WifiAwareClientState client = mClients.get(clientId);
4138         if (client == null) {
4139             Log.e(TAG, "updateSubscribeLocal: no client exists for clientId=" + clientId);
4140             return false;
4141         }
4142 
4143         WifiAwareDiscoverySessionState session = client.getSession(sessionId);
4144         if (session == null) {
4145             Log.e(TAG, "updateSubscribeLocal: no session exists for clientId=" + clientId
4146                     + ", sessionId=" + sessionId);
4147             return false;
4148         }
4149         AwarePairingConfig pairingConfig = subscribeConfig.getPairingConfig();
4150         byte[] nik = null;
4151         if (pairingConfig != null && pairingConfig.isPairingVerificationEnabled()) {
4152             nik = mPairingConfigManager.getNikForCallingPackage(
4153                     client.getCallingPackage());
4154         }
4155         boolean status = session.updateSubscribe(transactionId, subscribeConfig, nik);
4156         if (!status) {
4157             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE,
4158                     false, client.mCallerType, client.mCallingFeatureId);
4159         }
4160         return status;
4161     }
4162 
initiateNanPairingRequestLocal(short transactionId, int clientId, int sessionId, int peerId, String password, int requestType, int akm, byte[] pmk, int cipherSuite)4163     private boolean initiateNanPairingRequestLocal(short transactionId, int clientId, int sessionId,
4164             int peerId, String password, int requestType, int akm,
4165             byte[] pmk, int cipherSuite) {
4166         if (mVdbg) {
4167             Log.v(TAG, "initiateNanPairingRequestLocal: transactionId=" + transactionId
4168                     + ", clientId=" + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId);
4169         }
4170         WifiAwareClientState client = mClients.get(clientId);
4171         if (client == null) {
4172             Log.e(TAG, "initiateNanPairingRequestLocal: no client exists for clientId=" + clientId);
4173             return false;
4174         }
4175 
4176         WifiAwareDiscoverySessionState session = client.getSession(sessionId);
4177         if (session == null) {
4178             Log.e(TAG, "initiateNanPairingRequestLocal: no session exists for clientId="
4179                     + clientId + ", sessionId=" + sessionId);
4180             return false;
4181         }
4182         return session.initiatePairing(transactionId, peerId, password, requestType,
4183                 mPairingConfigManager.getNikForCallingPackage(client.getCallingPackage()),
4184                 pmk, akm, cipherSuite);
4185     }
4186 
respondToPairingRequestLocal(short transactionId, int clientId, int sessionId, int peerId, int pairingId, boolean accept, int requestType, byte[] pmk, String password, int akm, int cipherSuite)4187     private boolean respondToPairingRequestLocal(short transactionId, int clientId, int sessionId,
4188             int peerId, int pairingId, boolean accept, int requestType, byte[] pmk,
4189             String password, int akm, int cipherSuite) {
4190         if (mVdbg) {
4191             Log.v(TAG,
4192                     "respondToPairingRequestLocal: transactionId=" + transactionId + ", clientId="
4193                             + clientId + ", sessionId=" + sessionId + ", peerId="
4194                             + peerId);
4195         }
4196         WifiAwareClientState client = mClients.get(clientId);
4197         if (client == null) {
4198             Log.e(TAG, "respondToPairingRequestLocal: no client exists for clientId=" + clientId);
4199             return false;
4200         }
4201 
4202         WifiAwareDiscoverySessionState session = client.getSession(sessionId);
4203         if (session == null) {
4204             Log.e(TAG, "respondToPairingRequestLocal: no session exists for clientId=" + clientId
4205                     + ", sessionId=" + sessionId);
4206             return false;
4207         }
4208         return session.respondToPairingRequest(transactionId, peerId, pairingId,
4209                 accept,
4210                 mPairingConfigManager.getNikForCallingPackage(client.getCallingPackage()),
4211                 requestType, pmk, password, akm, cipherSuite);
4212     }
4213 
initiateBootstrappingRequestLocal(short transactionId, int clientId, int sessionId, int peerId, int method, byte[] cookie, boolean isComeBack)4214     private boolean initiateBootstrappingRequestLocal(short transactionId, int clientId,
4215             int sessionId, int peerId, int method, byte[] cookie, boolean isComeBack) {
4216         String methodString = "initiateBootstrappingRequestLocal";
4217         if (mVdbg) {
4218             Log.v(TAG, methodString + ": transactionId=" + transactionId
4219                     + ", clientId=" + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId);
4220         }
4221         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
4222                 methodString);
4223         if (session == null) {
4224             return false;
4225         }
4226         return session.initiateBootstrapping(transactionId, peerId, method, cookie, isComeBack);
4227     }
4228 
respondToBootstrappingRequestLocal(short transactionId, int clientId, int sessionId, int peerId, int bootstrappingId, boolean accept, int method)4229     private boolean respondToBootstrappingRequestLocal(short transactionId, int clientId,
4230             int sessionId, int peerId, int bootstrappingId, boolean accept, int method) {
4231         String methodString = "respondToBootstrappingRequestLocal";
4232         if (mVdbg) {
4233             Log.v(TAG, methodString + ": transactionId=" + transactionId
4234                     + ", clientId=" + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId);
4235         }
4236         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
4237                 methodString);
4238         if (session == null) {
4239             return false;
4240         }
4241         return session.respondToBootstrapping(transactionId, peerId, bootstrappingId, accept,
4242                 method);
4243     }
4244 
sendFollowonMessageLocal(short transactionId, int clientId, int sessionId, int peerId, byte[] message, int messageId)4245     private boolean sendFollowonMessageLocal(short transactionId, int clientId, int sessionId,
4246             int peerId, byte[] message, int messageId) {
4247         String methodString = "sendFollowonMessageLocal";
4248         if (mVdbg) {
4249             Log.v(TAG, methodString + "(): transactionId=" + transactionId + ", clientId="
4250                     + clientId + ", sessionId=" + sessionId + ", peerId=" + peerId
4251                     + ", messageId=" + messageId);
4252         }
4253 
4254         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
4255                 methodString);
4256         if (session == null) {
4257             return false;
4258         }
4259 
4260         return session.sendMessage(transactionId, peerId, message, messageId);
4261     }
4262 
enableUsageLocal()4263     private void enableUsageLocal() {
4264         Log.d(TAG, "enableUsageLocal: mUsageEnabled=" + mUsageEnabled);
4265 
4266         if (mUsageEnabled) {
4267             return;
4268         }
4269         mUsageEnabled = true;
4270         sendAwareStateChangedBroadcast(true);
4271 
4272         mAwareMetrics.recordEnableUsage();
4273     }
4274 
disableUsageLocal(short transactionId, boolean markAsAvailable)4275     private void disableUsageLocal(short transactionId, boolean markAsAvailable) {
4276         Log.d(TAG, "disableUsageLocal: transactionId=" + transactionId + ", mUsageEnabled="
4277                     + mUsageEnabled);
4278 
4279         if (!mUsageEnabled) {
4280             return;
4281         }
4282         onAwareDownLocal();
4283 
4284         mUsageEnabled = markAsAvailable;
4285         mCurrentRangingEnabled = false;
4286         mCurrentIdentityNotification = false;
4287         mInstantCommModeClientRequest = INSTANT_MODE_DISABLED;
4288         mAwareMetrics.reportAwareInstantModeEnabled(false);
4289         deferDisableAware(true);
4290         sendAwareStateChangedBroadcast(markAsAvailable);
4291         if (!markAsAvailable) {
4292             mAwareMetrics.recordDisableUsage();
4293         }
4294     }
4295 
initiateDataPathSetupLocal(short transactionId, WifiAwareNetworkSpecifier networkSpecifier, int peerId, int channelRequestType, int channel, byte[] peer, String interfaceName, boolean isOutOfBand, byte[] appInfo)4296     private boolean initiateDataPathSetupLocal(short transactionId,
4297             WifiAwareNetworkSpecifier networkSpecifier, int peerId, int channelRequestType,
4298             int channel, byte[] peer, String interfaceName,
4299             boolean isOutOfBand, byte[] appInfo) {
4300         WifiAwareDataPathSecurityConfig securityConfig = networkSpecifier
4301                 .getWifiAwareDataPathSecurityConfig();
4302         if (mVerboseLoggingEnabled) {
4303             Log.v(TAG, "initiateDataPathSetupLocal(): transactionId=" + transactionId
4304                     + ", networkSpecifier=" + networkSpecifier + ", peerId=" + peerId
4305                     + ", channelRequestType=" + channelRequestType + ", channel=" + channel
4306                     + ", peer="
4307                     + String.valueOf(HexEncoding.encode(peer)) + ", interfaceName=" + interfaceName
4308                     + ", securityConfig=" + ((securityConfig == null) ? "" : securityConfig)
4309                     + ", isOutOfBand="
4310                     + isOutOfBand + ", appInfo=" + (appInfo == null ? "<null>" : "<non-null>"));
4311         }
4312         byte pubSubId = 0;
4313         if (!isOutOfBand) {
4314             WifiAwareClientState client = mClients.get(networkSpecifier.clientId);
4315             if (client == null) {
4316                 Log.e(TAG, "initiateDataPathSetupLocal: no client exists for clientId="
4317                         + networkSpecifier.clientId);
4318                 return false;
4319             }
4320 
4321             WifiAwareDiscoverySessionState session = client.getSession(networkSpecifier.sessionId);
4322             if (session == null) {
4323                 Log.e(TAG, "initiateDataPathSetupLocal: no session exists for clientId="
4324                         + networkSpecifier.clientId + ", sessionId=" + networkSpecifier.sessionId);
4325                 return false;
4326             }
4327             pubSubId = (byte) session.getPubSubId();
4328         }
4329         boolean success = mWifiAwareNativeApi.initiateDataPath(transactionId, peerId,
4330                 channelRequestType, channel, peer, interfaceName, isOutOfBand,
4331                 appInfo, mCapabilities, networkSpecifier.getWifiAwareDataPathSecurityConfig(),
4332                 pubSubId);
4333         if (!success) {
4334             mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusCode.INTERNAL_FAILURE);
4335         }
4336 
4337         return success;
4338     }
4339 
respondToDataPathRequestLocal(short transactionId, boolean accept, int ndpId, String interfaceName, byte[] appInfo, boolean isOutOfBand, WifiAwareNetworkSpecifier networkSpecifier)4340     private boolean respondToDataPathRequestLocal(short transactionId, boolean accept,
4341             int ndpId, String interfaceName, byte[] appInfo, boolean isOutOfBand,
4342             WifiAwareNetworkSpecifier networkSpecifier) {
4343         WifiAwareDataPathSecurityConfig securityConfig = accept ? networkSpecifier
4344                 .getWifiAwareDataPathSecurityConfig() : null;
4345         if (mVerboseLoggingEnabled) {
4346             Log.v(TAG, "respondToDataPathRequestLocal(): transactionId=" + transactionId
4347                     + ", accept=" + accept + ", ndpId=" + ndpId + ", interfaceName=" + interfaceName
4348                     + ", securityConfig=" + securityConfig
4349                     + ", isOutOfBand=" + isOutOfBand
4350                     + ", appInfo=" + (appInfo == null ? "<null>" : "<non-null>"));
4351         }
4352         byte pubSubId = 0;
4353         if (!isOutOfBand && accept) {
4354             WifiAwareClientState client = mClients.get(networkSpecifier.clientId);
4355             if (client == null) {
4356                 Log.e(TAG, "respondToDataPathRequestLocal: no client exists for clientId="
4357                         + networkSpecifier.clientId);
4358                 return false;
4359             }
4360 
4361             WifiAwareDiscoverySessionState session = client.getSession(networkSpecifier.sessionId);
4362             if (session == null) {
4363                 Log.e(TAG, "respondToDataPathRequestLocal: no session exists for clientId="
4364                         + networkSpecifier.clientId + ", sessionId=" + networkSpecifier.sessionId);
4365                 return false;
4366             }
4367             pubSubId = (byte) session.getPubSubId();
4368         }
4369         boolean success = mWifiAwareNativeApi.respondToDataPathRequest(transactionId, accept, ndpId,
4370                 interfaceName, appInfo, isOutOfBand, mCapabilities, securityConfig, pubSubId);
4371         if (!success) {
4372             mDataPathMgr.onRespondToDataPathRequest(ndpId, false, NanStatusCode.INTERNAL_FAILURE);
4373         } else {
4374             sendAwareResourcesChangedBroadcast();
4375         }
4376         return success;
4377     }
4378 
endDataPathLocal(short transactionId, int ndpId)4379     private boolean endDataPathLocal(short transactionId, int ndpId) {
4380         if (mVerboseLoggingEnabled) {
4381             Log.v(TAG, "endDataPathLocal: transactionId=" + transactionId + ", ndpId=" + ndpId);
4382         }
4383         sendAwareResourcesChangedBroadcast();
4384         return mWifiAwareNativeApi.endDataPath(transactionId, ndpId);
4385     }
4386 
endPairingLocal(short transactionId, int pairId)4387     private boolean endPairingLocal(short transactionId, int pairId) {
4388         if (mVerboseLoggingEnabled) {
4389             Log.v(TAG, "endPairingLocal: transactionId=" + transactionId + ", pairId=" + pairId);
4390         }
4391         return mWifiAwareNativeApi.endPairing(transactionId, pairId);
4392     }
4393 
4394     /*
4395      * RESPONSES
4396      */
4397 
onConfigCompletedLocal(Message completedCommand)4398     private void onConfigCompletedLocal(Message completedCommand) {
4399         Log.d(TAG, "onConfigCompleted: completedCommand=" + completedCommand);
4400 
4401         if (completedCommand.arg1 == COMMAND_TYPE_CONNECT) {
4402             if (mCurrentAwareConfiguration == null) { // enabled (as opposed to re-configured)
4403                 queryCapabilities();
4404                 mDataPathMgr.createAllInterfaces();
4405                 recordHalApiCall(COMMAND_TYPE_CONNECT, NanStatusCode.SUCCESS, mStartTime);
4406             } else {
4407                 recordHalApiCall(COMMAND_TYPE_RECONFIGURE, NanStatusCode.SUCCESS, mStartTime);
4408             }
4409 
4410             Bundle data = completedCommand.getData();
4411 
4412             int clientId = completedCommand.arg2;
4413             Pair<IWifiAwareEventCallback, Object> callbackAndAttributionSource =
4414                     (Pair<IWifiAwareEventCallback, Object>) completedCommand.obj;
4415             IWifiAwareEventCallback callback = callbackAndAttributionSource.first;
4416             ConfigRequest configRequest = (ConfigRequest) data
4417                     .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
4418             int uid = data.getInt(MESSAGE_BUNDLE_KEY_UID);
4419             int pid = data.getInt(MESSAGE_BUNDLE_KEY_PID);
4420             boolean notifyIdentityChange = data.getBoolean(
4421                     MESSAGE_BUNDLE_KEY_NOTIFY_IDENTITY_CHANGE);
4422             String callingPackage = data.getString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE);
4423             String callingFeatureId = data.getString(MESSAGE_BUNDLE_KEY_CALLING_FEATURE_ID);
4424             boolean awareOffload = data.getBoolean(MESSAGE_BUNDLE_KEY_AWARE_OFFLOAD);
4425             int callerType = data.getInt(MESSAGE_BUNDLE_KEY_CALLER_TYPE);
4426 
4427             WifiAwareClientState client = new WifiAwareClientState(mContext, clientId, uid, pid,
4428                     callingPackage, callingFeatureId, callback, configRequest, notifyIdentityChange,
4429                     SystemClock.elapsedRealtime(), mWifiPermissionsUtil,
4430                     callbackAndAttributionSource.second, awareOffload, callerType);
4431             client.enableVerboseLogging(mVerboseLoggingEnabled, mVdbg);
4432             mClients.put(clientId, client);
4433             mAwareMetrics.recordAttachSession(uid, notifyIdentityChange, mClients, callerType,
4434                     callingFeatureId);
4435             try {
4436                 if (mVdbg) {
4437                     Log.v(TAG, "Connect success for clientId:" + clientId);
4438                 }
4439                 callback.onConnectSuccess(clientId);
4440             } catch (RemoteException e) {
4441                 Log.w(TAG,
4442                         "onConfigCompletedLocal onConnectSuccess(): RemoteException (FYI): " + e);
4443             }
4444             client.onClusterChange(mClusterEventType, mClusterId, mCurrentDiscoveryInterfaceMac);
4445         } else if (completedCommand.arg1 == COMMAND_TYPE_DISCONNECT) {
4446             recordHalApiCall(COMMAND_TYPE_RECONFIGURE, NanStatusCode.SUCCESS, mStartTime);
4447             /*
4448              * NOP (i.e. updated configuration after disconnecting a client)
4449              */
4450         } else if (completedCommand.arg1 == COMMAND_TYPE_RECONFIGURE) {
4451             recordHalApiCall(COMMAND_TYPE_RECONFIGURE, NanStatusCode.SUCCESS, mStartTime);
4452             /*
4453              * NOP (i.e. updated configuration at power saving event)
4454              */
4455         } else {
4456             Log.wtf(TAG, "onConfigCompletedLocal: unexpected completedCommand=" + completedCommand);
4457             return;
4458         }
4459 
4460         mCurrentAwareConfiguration = mergeConfigRequests(null);
4461         if (mCurrentAwareConfiguration == null) {
4462             Log.wtf(TAG, "onConfigCompletedLocal: got a null merged configuration after config!?");
4463         }
4464         mCurrentIdentityNotification = doesAnyClientNeedIdentityChangeNotifications();
4465         mCurrentRangingEnabled = doesAnyClientNeedRanging();
4466         mInstantCommModeClientRequest = getInstantModeFromAllClients();
4467         if (mInstantCommModeClientRequest == INSTANT_MODE_DISABLED) {
4468             mAwareMetrics.reportAwareInstantModeEnabled(false);
4469             return;
4470         }
4471         mAwareMetrics.reportAwareInstantModeEnabled(true);
4472         if (!mInstantCommModeGlobalEnable) {
4473             // Change the instant communication mode when timeout
4474             mHandler.postDelayed(this::reconfigure, (long) mContext.getResources()
4475                     .getInteger(R.integer.config_wifiAwareInstantCommunicationModeDurationMillis));
4476         }
4477     }
4478 
onConfigFailedLocal(Message failedCommand, int reason)4479     private void onConfigFailedLocal(Message failedCommand, int reason) {
4480         if (mVdbg) {
4481             Log.v(TAG,
4482                     "onConfigFailedLocal: failedCommand=" + failedCommand + ", reason=" + reason);
4483         }
4484 
4485         if (failedCommand.arg1 == COMMAND_TYPE_CONNECT) {
4486             mWifiAwareNativeManager.releaseAware();
4487             Pair<IWifiAwareEventCallback, Object> callbackAndAttributionSource =
4488                     (Pair<IWifiAwareEventCallback, Object>) failedCommand.obj;
4489             IWifiAwareEventCallback callback = callbackAndAttributionSource.first;
4490             try {
4491                 callback.onConnectFail(reason);
4492                 mAwareMetrics.recordAttachStatus(reason, 0, null, 0);
4493             } catch (RemoteException e) {
4494                 Log.w(TAG, "onConfigFailedLocal onConnectFail(): RemoteException (FYI): " + e);
4495             }
4496             recordHalApiCall(COMMAND_TYPE_CONNECT, reason, mStartTime);
4497         } else if (failedCommand.arg1 == COMMAND_TYPE_DISCONNECT) {
4498             recordHalApiCall(COMMAND_TYPE_RECONFIGURE, reason, mStartTime);
4499             /*
4500              * NOP (tried updating configuration after disconnecting a client -
4501              * shouldn't fail but there's nothing to do - the old configuration
4502              * is still up-and-running).
4503              *
4504              * OR: timed-out getting a response to a disable. Either way a NOP.
4505              */
4506         } else if (failedCommand.arg1 == COMMAND_TYPE_RECONFIGURE) {
4507             recordHalApiCall(COMMAND_TYPE_RECONFIGURE, reason, mStartTime);
4508             /*
4509              * NOP (configuration change as part of possibly power saving event - should not
4510              * fail but there's nothing to do).
4511              */
4512         } else {
4513             Log.wtf(TAG, "onConfigFailedLocal: unexpected failedCommand=" + failedCommand);
4514         }
4515     }
4516 
onDisableResponseLocal(Message command, int reason)4517     private void onDisableResponseLocal(Message command, int reason) {
4518         Log.d(TAG, "onDisableResponseLocal: command=" + command + ", reason=" + reason);
4519         /*
4520          * do nothing:
4521          * - success: was waiting so that don't enable while disabling
4522          * - fail: shouldn't happen (though can if already disabled for instance)
4523          */
4524         if (reason != NanStatusCode.SUCCESS) {
4525             Log.e(TAG, "onDisableResponseLocal: FAILED!? command=" + command + ", reason="
4526                     + reason);
4527         }
4528 
4529         boolean releaseAware = (boolean) command.obj;
4530         if (releaseAware) {
4531             // Need to release Aware
4532             mWifiAwareNativeManager.releaseAware();
4533         }
4534         mAwareMetrics.recordDisableAware();
4535     }
4536 
onSessionConfigSuccessLocal(Message completedCommand, byte pubSubId, boolean isPublish)4537     private void onSessionConfigSuccessLocal(Message completedCommand, byte pubSubId,
4538             boolean isPublish) {
4539         if (mVdbg) {
4540             Log.v(TAG, "onSessionConfigSuccessLocal: completedCommand=" + completedCommand
4541                     + ", pubSubId=" + pubSubId + ", isPublish=" + isPublish);
4542         }
4543 
4544         boolean isRangingEnabled;
4545         boolean enableInstantMode;
4546         boolean isSuspendable;
4547         int instantModeBand;
4548         int minRange = -1;
4549         int maxRange = -1;
4550         AwarePairingConfig pairingConfig;
4551         if (isPublish) {
4552             PublishConfig publishConfig = completedCommand.getData().getParcelable(
4553                     MESSAGE_BUNDLE_KEY_CONFIG);
4554             isRangingEnabled = publishConfig.mEnableRanging;
4555             enableInstantMode = publishConfig.isInstantCommunicationModeEnabled();
4556             isSuspendable = SdkLevel.isAtLeastU() && publishConfig.isSuspendable();
4557             instantModeBand = publishConfig.getInstantCommunicationBand();
4558             pairingConfig = publishConfig.getPairingConfig();
4559         } else {
4560             SubscribeConfig subscribeConfig = completedCommand.getData().getParcelable(
4561                     MESSAGE_BUNDLE_KEY_CONFIG);
4562             isRangingEnabled =
4563                     subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet;
4564             isSuspendable = SdkLevel.isAtLeastU() && subscribeConfig.isSuspendable();
4565             if (subscribeConfig.mMinDistanceMmSet) {
4566                 minRange = subscribeConfig.mMinDistanceMm;
4567             }
4568             if (subscribeConfig.mMaxDistanceMmSet) {
4569                 maxRange = subscribeConfig.mMaxDistanceMm;
4570             }
4571             enableInstantMode = subscribeConfig.isInstantCommunicationModeEnabled();
4572             instantModeBand = subscribeConfig.getInstantCommunicationBand();
4573             pairingConfig = subscribeConfig.getPairingConfig();
4574         }
4575 
4576         if (completedCommand.arg1 == COMMAND_TYPE_PUBLISH
4577                 || completedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) {
4578             int clientId = completedCommand.arg2;
4579             IWifiAwareDiscoverySessionCallback callback =
4580                     (IWifiAwareDiscoverySessionCallback) completedCommand.obj;
4581 
4582             WifiAwareClientState client = mClients.get(clientId);
4583             if (client == null) {
4584                 Log.e(TAG,
4585                         "onSessionConfigSuccessLocal: no client exists for clientId=" + clientId);
4586                 return;
4587             }
4588 
4589             int sessionId = mSm.mNextSessionId++;
4590             try {
4591                 if (mVdbg) {
4592                     Log.v(TAG,
4593                             (isPublish ? "publish" : "subscribe") + " session started, sessionId="
4594                                     + sessionId);
4595                 }
4596                 callback.onSessionStarted(sessionId);
4597             } catch (RemoteException e) {
4598                 Log.e(TAG, "onSessionConfigSuccessLocal: onSessionStarted() RemoteException=" + e);
4599                 return;
4600             }
4601 
4602             WifiAwareDiscoverySessionState session = new WifiAwareDiscoverySessionState(
4603                     mWifiAwareNativeApi, sessionId, pubSubId, callback, isPublish, isRangingEnabled,
4604                     SystemClock.elapsedRealtime(), enableInstantMode, instantModeBand,
4605                     isSuspendable, pairingConfig);
4606             session.enableVerboseLogging(mVerboseLoggingEnabled);
4607             client.addSession(session);
4608 
4609             if (isRangingEnabled) {
4610                 mAwareMetrics.recordDiscoverySessionWithRanging(client.getUid(),
4611                         completedCommand.arg1 != COMMAND_TYPE_PUBLISH, minRange, maxRange,
4612                         mClients);
4613             } else {
4614                 mAwareMetrics.recordDiscoverySession(client.getUid(), mClients);
4615             }
4616             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.SUCCESS,
4617                     completedCommand.arg1 == COMMAND_TYPE_PUBLISH, sessionId,
4618                     client.mCallerType, client.mCallingFeatureId);
4619             sendAwareResourcesChangedBroadcast();
4620         } else if (completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH
4621                 || completedCommand.arg1 == COMMAND_TYPE_UPDATE_SUBSCRIBE) {
4622             int clientId = completedCommand.arg2;
4623             int sessionId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
4624 
4625             WifiAwareClientState client = mClients.get(clientId);
4626             if (client == null) {
4627                 Log.e(TAG,
4628                         "onSessionConfigSuccessLocal: no client exists for clientId=" + clientId);
4629                 return;
4630             }
4631 
4632             WifiAwareDiscoverySessionState session = client.getSession(sessionId);
4633             if (session == null) {
4634                 Log.e(TAG, "onSessionConfigSuccessLocal: no session exists for clientId=" + clientId
4635                         + ", sessionId=" + sessionId);
4636                 return;
4637             }
4638 
4639             try {
4640                 session.getCallback().onSessionConfigSuccess();
4641             } catch (RemoteException e) {
4642                 Log.e(TAG, "onSessionConfigSuccessLocal: onSessionConfigSuccess() RemoteException="
4643                         + e);
4644             }
4645             session.setRangingEnabled(isRangingEnabled);
4646             session.setInstantModeEnabled(enableInstantMode);
4647             session.setInstantModeBand(instantModeBand);
4648             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.SUCCESS,
4649                     completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH,
4650                     client.mCallerType, client.mCallingFeatureId);
4651         } else {
4652             Log.wtf(TAG,
4653                     "onSessionConfigSuccessLocal: unexpected completedCommand=" + completedCommand);
4654             return;
4655         }
4656         // If Ranging enabled or instant mode require changes, reconfigure.
4657         if (mCurrentRangingEnabled != doesAnyClientNeedRanging()
4658                 || mInstantCommModeClientRequest != getInstantModeFromAllClients()) {
4659             reconfigure();
4660         }
4661     }
4662 
onSessionConfigFailLocal(Message failedCommand, boolean isPublish, int reason)4663     private void onSessionConfigFailLocal(Message failedCommand, boolean isPublish, int reason) {
4664         if (mVdbg) {
4665             Log.v(TAG, "onSessionConfigFailLocal: failedCommand=" + failedCommand + ", isPublish="
4666                     + isPublish + ", reason=" + reason);
4667         }
4668 
4669         if (failedCommand.arg1 == COMMAND_TYPE_PUBLISH
4670                 || failedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) {
4671             int clientId = failedCommand.arg2;
4672             IWifiAwareDiscoverySessionCallback callback =
4673                     (IWifiAwareDiscoverySessionCallback) failedCommand.obj;
4674 
4675             WifiAwareClientState client = mClients.get(clientId);
4676             if (client == null) {
4677                 Log.e(TAG, "onSessionConfigFailLocal: no client exists for clientId=" + clientId);
4678                 return;
4679             }
4680 
4681             try {
4682                 callback.onSessionConfigFail(reason);
4683             } catch (RemoteException e) {
4684                 Log.w(TAG, "onSessionConfigFailLocal onSessionConfigFail(): RemoteException (FYI): "
4685                         + e);
4686             }
4687             mAwareMetrics.recordDiscoveryStatus(client.getUid(), reason,
4688                     failedCommand.arg1 == COMMAND_TYPE_PUBLISH, client.mCallerType,
4689                     client.mCallingFeatureId);
4690         } else if (failedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH
4691                 || failedCommand.arg1 == COMMAND_TYPE_UPDATE_SUBSCRIBE) {
4692             int clientId = failedCommand.arg2;
4693             int sessionId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
4694 
4695             WifiAwareClientState client = mClients.get(clientId);
4696             if (client == null) {
4697                 Log.e(TAG, "onSessionConfigFailLocal: no client exists for clientId=" + clientId);
4698                 return;
4699             }
4700 
4701             WifiAwareDiscoverySessionState session = client.getSession(sessionId);
4702             if (session == null) {
4703                 Log.e(TAG, "onSessionConfigFailLocal: no session exists for clientId=" + clientId
4704                         + ", sessionId=" + sessionId);
4705                 return;
4706             }
4707 
4708             try {
4709                 session.getCallback().onSessionConfigFail(reason);
4710             } catch (RemoteException e) {
4711                 Log.e(TAG, "onSessionConfigFailLocal: onSessionConfigFail() RemoteException=" + e);
4712             }
4713             mAwareMetrics.recordDiscoveryStatus(client.getUid(), reason,
4714                     failedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH, client.mCallerType,
4715                     client.mCallingFeatureId);
4716 
4717             if (reason == NanStatusCode.INVALID_SESSION_ID) {
4718                 client.removeSession(sessionId);
4719                 // If Ranging enabled or instant mode require changes, reconfigure.
4720                 if (mCurrentRangingEnabled != doesAnyClientNeedRanging()
4721                         || mInstantCommModeClientRequest != getInstantModeFromAllClients()) {
4722                     reconfigure();
4723                 }
4724                 sendAwareResourcesChangedBroadcast();
4725             }
4726         } else {
4727             Log.wtf(TAG, "onSessionConfigFailLocal: unexpected failedCommand=" + failedCommand);
4728         }
4729     }
4730 
onMessageSendSuccessLocal(Message completedCommand)4731     private void onMessageSendSuccessLocal(Message completedCommand) {
4732         String methodString = "onMessageSendSuccessLocal";
4733         if (mVdbg) {
4734             Log.v(TAG, methodString + ": completedCommand=" + completedCommand);
4735         }
4736 
4737         int clientId = completedCommand.arg2;
4738         int sessionId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
4739         int messageId = completedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID);
4740 
4741         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
4742                 methodString);
4743         if (session == null) {
4744             return;
4745         }
4746 
4747         try {
4748             session.getCallback().onMessageSendSuccess(messageId);
4749         } catch (RemoteException e) {
4750             Log.w(TAG, "onMessageSendSuccessLocal: RemoteException (FYI): " + e);
4751         }
4752     }
4753 
onMessageSendFailLocal(Message failedCommand, int reason)4754     private void onMessageSendFailLocal(Message failedCommand, int reason) {
4755         String methodString = "onMessageSendFailLocal";
4756         if (mVdbg) {
4757             Log.v(TAG, methodString + ": failedCommand=" + failedCommand + ", reason=" + reason);
4758         }
4759 
4760         int clientId = failedCommand.arg2;
4761         int sessionId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
4762         int messageId = failedCommand.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID);
4763 
4764         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
4765                 methodString);
4766         if (session == null) {
4767             return;
4768         }
4769 
4770         try {
4771             session.getCallback().onMessageSendFail(messageId, reason);
4772         } catch (RemoteException e) {
4773             Log.e(TAG, "onMessageSendFailLocal: onMessageSendFail RemoteException=" + e);
4774         }
4775     }
4776 
onCapabilitiesUpdatedResponseLocal(Capabilities capabilities)4777     private void onCapabilitiesUpdatedResponseLocal(Capabilities capabilities) {
4778         if (mVdbg) {
4779             Log.v(TAG, "onCapabilitiesUpdatedResponseLocal: capabilites=" + capabilities);
4780         }
4781 
4782         mCapabilities = capabilities;
4783         mCharacteristics = null;
4784         if (mWifiAwarePullAtomCallback != null) {
4785             //Should only register this callback once
4786             return;
4787         }
4788         StatsManager statsManager = mContext.getSystemService(StatsManager.class);
4789         if (statsManager != null) {
4790             mWifiAwarePullAtomCallback = new WifiAwarePullAtomCallback();
4791             statsManager.setPullAtomCallback(WIFI_AWARE_CAPABILITIES, null,
4792                     new HandlerExecutor(mHandler), mWifiAwarePullAtomCallback);
4793         }
4794     }
4795     private class WifiAwarePullAtomCallback implements StatsManager.StatsPullAtomCallback {
4796 
4797         @Override
onPullAtom(int atomTag, @androidx.annotation.NonNull List<StatsEvent> data)4798         public int onPullAtom(int atomTag, @androidx.annotation.NonNull List<StatsEvent> data) {
4799             data.add(WifiStatsLog.buildStatsEvent(atomTag,
4800                     mCapabilities.isInstantCommunicationModeSupported,
4801                     mCapabilities.isNanPairingSupported,
4802                     mCapabilities.isSuspensionSupported,
4803                     mCapabilities.supportedDataPathCipherSuites,
4804                     mCapabilities.maxNdiInterfaces,
4805                     mCapabilities.maxNdpSessions,
4806                     mCapabilities.maxPublishes));
4807             return StatsManager.PULL_SUCCESS;
4808         }
4809     }
4810 
onCreateDataPathInterfaceResponseLocal(Message command, boolean success, int reasonOnFailure)4811     private void onCreateDataPathInterfaceResponseLocal(Message command, boolean success,
4812             int reasonOnFailure) {
4813         if (mVdbg) {
4814             Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: command=" + command + ", success="
4815                     + success + ", reasonOnFailure=" + reasonOnFailure);
4816         }
4817 
4818         if (success) {
4819             if (mVdbg) {
4820                 Log.v(TAG, "onCreateDataPathInterfaceResponseLocal: successfully created interface "
4821                         + command.obj);
4822             }
4823             mDataPathMgr.onInterfaceCreated((String) command.obj);
4824         } else {
4825             Log.e(TAG,
4826                     "onCreateDataPathInterfaceResponseLocal: failed when trying to create "
4827                             + "interface "
4828                             + command.obj + ". Reason code=" + reasonOnFailure);
4829         }
4830     }
4831 
onDeleteDataPathInterfaceResponseLocal(Message command, boolean success, int reasonOnFailure)4832     private void onDeleteDataPathInterfaceResponseLocal(Message command, boolean success,
4833             int reasonOnFailure) {
4834         if (mVdbg) {
4835             Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: command=" + command + ", success="
4836                     + success + ", reasonOnFailure=" + reasonOnFailure);
4837         }
4838 
4839         if (success) {
4840             if (mVdbg) {
4841                 Log.v(TAG, "onDeleteDataPathInterfaceResponseLocal: successfully deleted interface "
4842                         + command.obj);
4843             }
4844             mDataPathMgr.onInterfaceDeleted((String) command.obj);
4845         } else {
4846             Log.e(TAG,
4847                     "onDeleteDataPathInterfaceResponseLocal: failed when trying to delete "
4848                             + "interface "
4849                             + command.obj + ". Reason code=" + reasonOnFailure);
4850         }
4851     }
4852 
onRespondToPairingIndicationResponseSuccessLocal(Message command)4853     private boolean onRespondToPairingIndicationResponseSuccessLocal(Message command) {
4854         String methodString = "onRespondToPairingIndicationResponseSuccessLocal";
4855         if (mVdbg) {
4856             Log.v(TAG, methodString + ": command=" + command);
4857         }
4858         Bundle data = command.getData();
4859         PairingInfo pairingInfo = new PairingInfo(command.arg2,
4860                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4861                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
4862                 data.getString(MESSAGE_BUNDLE_KEY_PAIRING_ALIAS));
4863         int requestId = data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_REQUEST_ID);
4864 
4865         WifiAwareDiscoverySessionState session = getClientSession(pairingInfo.mClientId,
4866                 pairingInfo.mSessionId, methodString);
4867         if (session == null) {
4868             return false;
4869         }
4870         mPairingRequest.append(requestId, pairingInfo);
4871         return true;
4872     }
4873 
onRespondToPairingIndicationResponseFail(Message command, int reason)4874     private void onRespondToPairingIndicationResponseFail(Message command, int reason) {
4875         String methodString = "onRespondToPairingIndicationResponseFail";
4876         if (mVdbg) {
4877             Log.v(TAG, methodString + ": command=" + command + " reason=" + reason);
4878         }
4879 
4880         Bundle data = command.getData();
4881         PairingInfo pairingInfo = new PairingInfo(command.arg2,
4882                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4883                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
4884                 data.getString(MESSAGE_BUNDLE_KEY_PAIRING_ALIAS));
4885 
4886         WifiAwareDiscoverySessionState session = getClientSession(pairingInfo.mClientId,
4887                 pairingInfo.mSessionId, methodString);
4888         if (session == null) {
4889             return;
4890         }
4891         if (data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE) == NAN_PAIRING_REQUEST_TYPE_SETUP) {
4892             session.onPairingConfirmReceived(pairingInfo.mPeerId, false, pairingInfo.mAlias,
4893                     NAN_PAIRING_REQUEST_TYPE_SETUP);
4894         }
4895     }
4896 
onInitiateDataPathResponseSuccessLocal(Message command, int ndpId)4897     private boolean onInitiateDataPathResponseSuccessLocal(Message command, int ndpId) {
4898         return mDataPathMgr
4899                 .onDataPathInitiateSuccess((WifiAwareNetworkSpecifier) command.obj, ndpId);
4900     }
4901 
onInitiatePairingResponseSuccessLocal(Message command, int paireId)4902     private boolean onInitiatePairingResponseSuccessLocal(Message command, int paireId) {
4903         String methodString = "onInitiatePairingResponseSuccessLocal";
4904         if (mVdbg) {
4905             Log.v(TAG, methodString + ": command=" + command + ", ndpId=" + paireId);
4906         }
4907 
4908         Bundle data = command.getData();
4909         PairingInfo pairingInfo = new PairingInfo(command.arg2,
4910                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4911                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
4912                 data.getString(MESSAGE_BUNDLE_KEY_PAIRING_ALIAS));
4913 
4914         WifiAwareDiscoverySessionState session = getClientSession(pairingInfo.mClientId,
4915                 pairingInfo.mSessionId, methodString);
4916         if (session == null) {
4917             return false;
4918         }
4919 
4920         mPairingRequest.append(paireId, pairingInfo);
4921         return true;
4922     }
4923 
onInitiatePairingResponseFailLocal(Message command, int reason)4924     private void onInitiatePairingResponseFailLocal(Message command, int reason) {
4925         String methodString = "onInitiatePairingResponseFailLocal";
4926         if (mVdbg) {
4927             Log.v(TAG, methodString + ": command=" + command + ", reason=" + reason);
4928         }
4929 
4930         Bundle data = command.getData();
4931         PairingInfo pairingInfo = new PairingInfo(command.arg2,
4932                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4933                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
4934                 data.getString(MESSAGE_BUNDLE_KEY_PAIRING_ALIAS));
4935 
4936         WifiAwareDiscoverySessionState session = getClientSession(pairingInfo.mClientId,
4937                 pairingInfo.mSessionId, methodString);
4938         if (session == null) {
4939             return;
4940         }
4941         if (data.getInt(MESSAGE_BUNDLE_KEY_PAIRING_TYPE) == NAN_PAIRING_REQUEST_TYPE_SETUP) {
4942             session.onPairingConfirmReceived(pairingInfo.mPeerId, false, pairingInfo.mAlias,
4943                     NAN_PAIRING_REQUEST_TYPE_SETUP);
4944         }
4945     }
4946 
onInitiateBootstrappingResponseSuccessLocal(Message command, int id)4947     private boolean onInitiateBootstrappingResponseSuccessLocal(Message command, int id) {
4948         String methodString = "onInitiateBootstrappingResponseSuccessLocal";
4949         if (mVdbg) {
4950             Log.v(TAG, methodString + ": command=" + command + ", ndpId=" + id);
4951         }
4952 
4953         Bundle data = command.getData();
4954         BootStrppingInfo info = new BootStrppingInfo(command.arg2,
4955                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4956                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
4957                 data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD),
4958                 data.getBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_IS_COME_BACK_REQUEST));
4959         WifiAwareDiscoverySessionState session = getClientSession(info.mClientId, info.mSessionId,
4960                 methodString);
4961         if (session == null) {
4962             return false;
4963         }
4964 
4965         mBootstrappingRequest.append(id, info);
4966         return true;
4967     }
4968 
onInitiateBootStrappingResponseFailLocal(Message command, int reason)4969     private void onInitiateBootStrappingResponseFailLocal(Message command, int reason) {
4970         String methodString = "onInitiateBootStrappingResponseFailLocal";
4971         if (mVdbg) {
4972             Log.v(TAG, methodString + ": command=" + command + ", reason=" + reason);
4973         }
4974 
4975         Bundle data = command.getData();
4976         BootStrppingInfo info = new BootStrppingInfo(command.arg2,
4977                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4978                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
4979                 data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD),
4980                 data.getBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_IS_COME_BACK_REQUEST));
4981 
4982         WifiAwareDiscoverySessionState session = getClientSession(info.mClientId, info.mSessionId,
4983                 methodString);
4984         if (session == null) {
4985             return;
4986         }
4987         session.onBootStrappingConfirmReceived(info.mPeerId, false, info.mMethod);
4988     }
4989 
onRespondToBootStrappingRequestSuccessLocal(Message command)4990     private void onRespondToBootStrappingRequestSuccessLocal(Message command) {
4991         String methodString = "onRespondToBootStrappingRequestSuccessLocal";
4992         if (mVdbg) {
4993             Log.v(TAG, methodString + ": command=" + command);
4994         }
4995 
4996         Bundle data = command.getData();
4997         BootStrppingInfo info = new BootStrppingInfo(command.arg2,
4998                 data.getInt(MESSAGE_BUNDLE_KEY_SESSION_ID),
4999                 data.getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
5000                 data.getInt(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_METHOD),
5001                 data.getBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_IS_COME_BACK_REQUEST));
5002 
5003         WifiAwareDiscoverySessionState session = getClientSession(info.mClientId, info.mSessionId,
5004                 methodString);
5005         if (session == null) {
5006             return;
5007         }
5008         if (data.getBoolean(MESSAGE_BUNDLE_KEY_BOOTSTRAPPING_ACCEPT)) {
5009             session.onBootStrappingConfirmReceived(info.mPeerId, true, info.mMethod);
5010         }
5011     }
5012 
onSuspendResponseLocal(Message command, boolean success, int reason)5013     private void onSuspendResponseLocal(Message command, boolean success, int reason) {
5014         String methodString = "onSuspendResponseLocal";
5015         if (mVdbg) {
5016             Log.v(TAG, methodString + ": command=" + command + ", success=" + success
5017                     + ", reason=" + reason);
5018         }
5019 
5020         int clientId = command.arg2;
5021         int sessionId = command.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
5022 
5023         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
5024                 methodString);
5025         if (session == null) {
5026             return;
5027         }
5028         if (success) {
5029             session.onSuspendSuccess();
5030         } else {
5031             session.onSuspendFail(convertFrameworkStatusToSuspensionFailedReason(reason));
5032         }
5033     }
5034 
5035     @WifiAwareManager.SessionSuspensionFailedReasonCode
convertFrameworkStatusToSuspensionFailedReason(int reason)5036     private int convertFrameworkStatusToSuspensionFailedReason(int reason) {
5037         switch (reason) {
5038             case REDUNDANT_REQUEST:
5039                 return WIFI_AWARE_SUSPEND_REDUNDANT_REQUEST;
5040             case NOT_SUPPORTED:
5041                 return WIFI_AWARE_SUSPEND_INVALID_SESSION;
5042             case NO_CONNECTION:
5043                 return WIFI_AWARE_SUSPEND_CANNOT_SUSPEND;
5044             default:
5045                 return WIFI_AWARE_SUSPEND_INTERNAL_ERROR;
5046         }
5047     }
5048 
onResumeResponseLocal(Message command, boolean success, @WifiAwareManager.SessionResumptionFailedReasonCode int reason)5049     private void onResumeResponseLocal(Message command, boolean success,
5050             @WifiAwareManager.SessionResumptionFailedReasonCode int reason) {
5051         String methodString = "onResumeResponseLocal";
5052         if (mVdbg) {
5053             Log.v(TAG, methodString + ": command="
5054                     + command + ", success=" + success + ", reason=" + reason);
5055         }
5056 
5057         int clientId = command.arg2;
5058         int sessionId = command.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
5059 
5060         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
5061                 methodString);
5062         if (session == null) {
5063             return;
5064         }
5065         if (!success) {
5066             session.onResumeFail(convertFrameworkStatusToResumptionFailedReasonCode(reason));
5067         }
5068     }
5069 
5070     @WifiAwareManager.SessionResumptionFailedReasonCode
convertFrameworkStatusToResumptionFailedReasonCode(int reason)5071     private int convertFrameworkStatusToResumptionFailedReasonCode(int reason) {
5072         switch (reason) {
5073             case REDUNDANT_REQUEST:
5074                 return WIFI_AWARE_RESUME_REDUNDANT_REQUEST;
5075             case NOT_SUPPORTED:
5076                 return WIFI_AWARE_RESUME_INVALID_SESSION;
5077             default:
5078                 return WIFI_AWARE_RESUME_INTERNAL_ERROR;
5079         }
5080     }
5081 
5082 
5083 
onInitiateDataPathResponseFailLocal(Message command, int reason)5084     private void onInitiateDataPathResponseFailLocal(Message command, int reason) {
5085         if (mVdbg) {
5086             Log.v(TAG, "onInitiateDataPathResponseFailLocal: command=" + command + ", reason="
5087                     + reason);
5088         }
5089         mDataPathMgr.onDataPathInitiateFail((WifiAwareNetworkSpecifier) command.obj, reason);
5090     }
5091 
onRespondToDataPathSetupRequestResponseLocal(Message command, boolean success, int reasonOnFailure)5092     private boolean onRespondToDataPathSetupRequestResponseLocal(Message command, boolean success,
5093             int reasonOnFailure) {
5094         if (mVdbg) {
5095             Log.v(TAG, "onRespondToDataPathSetupRequestResponseLocal: command=" + command
5096                     + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure);
5097         }
5098 
5099         return mDataPathMgr.onRespondToDataPathRequest(command.arg2, success, reasonOnFailure);
5100     }
5101 
onEndPathEndResponseLocal(Message command, boolean success, int reasonOnFailure)5102     private void onEndPathEndResponseLocal(Message command, boolean success, int reasonOnFailure) {
5103         if (mVdbg) {
5104             Log.v(TAG, "onEndPathEndResponseLocal: command=" + command
5105                     + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure);
5106         }
5107         // TODO: do something with this
5108     }
5109 
onPairingEndResponseLocal(Message command, boolean success, int reasonOnFailure)5110     private void onPairingEndResponseLocal(Message command, boolean success, int reasonOnFailure) {
5111         if (mVdbg) {
5112             Log.v(TAG, "onPairingEndResponseLocal: command=" + command
5113                     + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure);
5114         }
5115     }
5116 
suspendSessionLocal(short transactionId, int clientId, int sessionId)5117     private boolean suspendSessionLocal(short transactionId, int clientId, int sessionId) {
5118         String methodString = "suspendSessionLocal";
5119         if (mVdbg) {
5120             Log.v(TAG, methodString + "(): transactionId=" + transactionId + ", clientId="
5121                     + clientId + ", sessionId=" + sessionId);
5122         }
5123 
5124         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
5125                 methodString);
5126         if (session == null) {
5127             return false;
5128         }
5129         if (!session.isSuspendable()) {
5130             session.onSuspendFail(WIFI_AWARE_SUSPEND_INVALID_SESSION);
5131             return false;
5132         }
5133         if (session.isSessionSuspended()) {
5134             session.onSuspendFail(WIFI_AWARE_SUSPEND_REDUNDANT_REQUEST);
5135             return false;
5136         }
5137 
5138         return session.suspend(transactionId);
5139     }
5140 
resumeSessionLocal(short transactionId, int clientId, int sessionId)5141     private boolean resumeSessionLocal(short transactionId, int clientId, int sessionId) {
5142         if (mVdbg) {
5143             Log.v(TAG, "resumeSessionLocal(): transactionId=" + transactionId + ", clientId="
5144                     + clientId + ", sessionId=" + sessionId);
5145         }
5146 
5147         String methodString = "resumeSessionLocal";
5148         WifiAwareDiscoverySessionState session = getClientSession(clientId, sessionId,
5149                 methodString);
5150         if (session == null) {
5151             return false;
5152         }
5153         if (!session.isSuspendable()) {
5154             session.onResumeFail(WIFI_AWARE_RESUME_INVALID_SESSION);
5155             return false;
5156         }
5157         if (!session.isSessionSuspended()) {
5158             session.onResumeFail(WIFI_AWARE_RESUME_REDUNDANT_REQUEST);
5159             return false;
5160         }
5161 
5162         return session.resume(transactionId);
5163     }
5164 
5165     /*
5166      * NOTIFICATIONS
5167      */
5168 
onInterfaceAddressChangeLocal(byte[] mac)5169     private void onInterfaceAddressChangeLocal(byte[] mac) {
5170         Log.d(TAG, "onInterfaceAddressChange: mac=" + String.valueOf(HexEncoding.encode(mac)));
5171 
5172         mCurrentDiscoveryInterfaceMac = mac;
5173 
5174         for (int i = 0; i < mClients.size(); ++i) {
5175             WifiAwareClientState client = mClients.valueAt(i);
5176             client.onInterfaceAddressChange(mac);
5177         }
5178 
5179         mAwareMetrics.recordEnableAware();
5180     }
5181 
onClusterChangeLocal(int clusterEventType, byte[] clusterId)5182     private void onClusterChangeLocal(int clusterEventType, byte[] clusterId) {
5183         mClusterId = clusterId;
5184         mClusterEventType = clusterEventType;
5185 
5186         if (mVdbg) {
5187             Log.v(TAG, "onClusterChange: clusterEventType=" + clusterEventType + ", clusterId="
5188                     + String.valueOf(HexEncoding.encode(clusterId)));
5189         }
5190 
5191         for (int i = 0; i < mClients.size(); ++i) {
5192             WifiAwareClientState client = mClients.valueAt(i);
5193             client.onClusterChange(clusterEventType, clusterId, mCurrentDiscoveryInterfaceMac);
5194         }
5195 
5196         mAwareMetrics.recordEnableAware();
5197     }
5198 
onMatchLocal(int pubSubId, int requestorinstanceid, byte[] peerMac, byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm, int cipherSuite, byte[] scid, byte[] nonce, byte[] tag, AwarePairingConfig pairingConfig, @NonNull List<OuiKeyedData> vendorData)5199     private void onMatchLocal(int pubSubId, int requestorinstanceid, byte[] peerMac,
5200             byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndication, int rangeMm,
5201             int cipherSuite, byte[] scid, byte[] nonce, byte[] tag,
5202             AwarePairingConfig pairingConfig, @NonNull List<OuiKeyedData> vendorData) {
5203         if (mVerboseLoggingEnabled) {
5204             Log.v(TAG, "onMatch: pubSubId=" + pubSubId
5205                     + ", requestorInstanceId=" + requestorinstanceid
5206                     + ", peerDiscoveryMac=" + String.valueOf(HexEncoding.encode(peerMac))
5207                     + ", serviceSpecificInfo=" + Arrays.toString(serviceSpecificInfo)
5208                     + ", matchFilter=" + Arrays.toString(matchFilter)
5209                     + ", rangingIndication=" + rangingIndication + ", rangeMm=" + rangeMm);
5210         }
5211 
5212         Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
5213                 getClientSessionForPubSubId(pubSubId);
5214         if (data == null) {
5215             Log.e(TAG, "onMatch: no session found for pubSubId=" + pubSubId);
5216             return;
5217         }
5218 
5219         if (data.second.isRangingEnabled()) {
5220             mAwareMetrics.recordMatchIndicationForRangeEnabledSubscribe(rangingIndication != 0);
5221         }
5222         String pairingAlias = mPairingConfigManager.getPairedDeviceAlias(
5223                 data.first.getCallingPackage(), nonce, tag, peerMac);
5224         int peerId = data.second.onMatch(requestorinstanceid, peerMac, serviceSpecificInfo,
5225                 matchFilter, rangingIndication, rangeMm, cipherSuite, scid, pairingAlias,
5226                 pairingConfig, vendorData);
5227         if (TextUtils.isEmpty(pairingAlias)) {
5228             return;
5229         }
5230         PairingSecurityAssociationInfo securityInfo = mPairingConfigManager
5231                 .getSecurityInfoPairedDevice(pairingAlias);
5232         if (securityInfo == null) {
5233             return;
5234         }
5235         initiateNanPairingVerificationRequest(data.first.getClientId(), data.second.getSessionId(),
5236                 peerId, pairingAlias, securityInfo.mNpk, securityInfo.mAkm,
5237                 securityInfo.mCipherSuite);
5238     }
5239 
onMatchExpiredLocal(int pubSubId, int requestorInstanceId)5240     private void onMatchExpiredLocal(int pubSubId, int requestorInstanceId) {
5241         if (mVdbg) {
5242             Log.v(TAG,
5243                     "onMatchExpiredNotification: pubSubId=" + pubSubId
5244                             + ", requestorInstanceId=" + requestorInstanceId);
5245         }
5246 
5247         Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
5248                 getClientSessionForPubSubId(pubSubId);
5249         if (data == null) {
5250             Log.e(TAG, "onMatch: no session found for pubSubId=" + pubSubId);
5251             return;
5252         }
5253         data.second.onMatchExpired(requestorInstanceId);
5254     }
5255 
onSessionTerminatedLocal(int pubSubId, boolean isPublish, int reason)5256     private void onSessionTerminatedLocal(int pubSubId, boolean isPublish, int reason) {
5257         if (mVerboseLoggingEnabled) {
5258             Log.v(TAG, "onSessionTerminatedLocal: pubSubId=" + pubSubId + ", isPublish=" + isPublish
5259                     + ", reason=" + reason);
5260         }
5261 
5262         Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
5263                 getClientSessionForPubSubId(pubSubId);
5264         if (data == null) {
5265             Log.e(TAG, "onSessionTerminatedLocal: no session found for pubSubId=" + pubSubId);
5266             return;
5267         }
5268 
5269         try {
5270             data.second.getCallback().onSessionTerminated(reason);
5271         } catch (RemoteException e) {
5272             Log.w(TAG,
5273                     "onSessionTerminatedLocal onSessionTerminated(): RemoteException (FYI): " + e);
5274         }
5275         data.first.removeSession(data.second.getSessionId());
5276         // If Ranging enabled or instant mode require changes, reconfigure.
5277         if (mCurrentRangingEnabled != doesAnyClientNeedRanging()
5278                 || mInstantCommModeClientRequest != getInstantModeFromAllClients()) {
5279             reconfigure();
5280         }
5281         mAwareMetrics.recordDiscoverySessionDuration(data.second.getCreationTime(),
5282                 data.second.isPublishSession(), data.second.getSessionId());
5283         sendAwareResourcesChangedBroadcast();
5284     }
5285 
onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac, byte[] message)5286     private void onMessageReceivedLocal(int pubSubId, int requestorInstanceId, byte[] peerMac,
5287             byte[] message) {
5288         if (mVerboseLoggingEnabled) {
5289             Log.v(TAG, "onMessageReceivedLocal: pubSubId=" + pubSubId + ", requestorInstanceId="
5290                     + requestorInstanceId + ", peerDiscoveryMac="
5291                     + String.valueOf(HexEncoding.encode(peerMac)));
5292         }
5293 
5294         Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
5295                 getClientSessionForPubSubId(pubSubId);
5296         if (data == null) {
5297             Log.e(TAG, "onMessageReceivedLocal: no session found for pubSubId=" + pubSubId);
5298             return;
5299         }
5300 
5301         data.second.onMessageReceived(requestorInstanceId, peerMac, message);
5302     }
5303 
onAwareDownLocal()5304     private void onAwareDownLocal() {
5305         Log.d(TAG, "onAwareDown: mCurrentAwareConfiguration=" + mCurrentAwareConfiguration);
5306 
5307         if (mCurrentAwareConfiguration == null) {
5308             return;
5309         }
5310 
5311         for (int i = 0; i < mClients.size(); ++i) {
5312             WifiAwareClientState client = mClients.valueAt(i);
5313             mAwareMetrics.recordAttachSessionDuration(client.getCreationTime());
5314             SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions();
5315             for (int j = 0; j < sessions.size(); ++j) {
5316                 mAwareMetrics.recordDiscoverySessionDuration(sessions.valueAt(j).getCreationTime(),
5317                         sessions.valueAt(j).isPublishSession(), sessions.valueAt(j).getSessionId());
5318             }
5319             client.destroy();
5320         }
5321         mAwareMetrics.recordDisableAware();
5322 
5323         mClients.clear();
5324         mPairingRequest.clear();
5325         mCurrentAwareConfiguration = null;
5326         mSm.onAwareDownCleanupSendQueueState();
5327         mDataPathMgr.onAwareDownCleanupDataPaths();
5328         mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC;
5329         mDataPathMgr.deleteAllInterfaces();
5330         sendAwareResourcesChangedBroadcast();
5331     }
5332 
onPairingRequestReceivedLocal(int discoverySessionId, int peerId, byte[] peerDiscMacAddr, int pairingId, int requestType, byte[] nonce, byte[] tag)5333     private void onPairingRequestReceivedLocal(int discoverySessionId, int peerId,
5334             byte[] peerDiscMacAddr, int pairingId, int requestType, byte[] nonce, byte[] tag) {
5335         Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
5336                 getClientSessionForPubSubId(discoverySessionId);
5337         if (data == null) {
5338             Log.e(TAG, "onPairingRequestReceivedLocal: no session found for pubSubId="
5339                     + discoverySessionId);
5340             return;
5341         }
5342         if (requestType == NAN_PAIRING_REQUEST_TYPE_SETUP) {
5343             data.second.onPairingRequestReceived(peerId, peerDiscMacAddr, pairingId);
5344             return;
5345         }
5346         // Response with the cache NPKSA
5347         String alias = mPairingConfigManager.getPairedDeviceAlias(
5348                 data.first.getCallingPackage(), nonce, tag, peerDiscMacAddr);
5349         PairingSecurityAssociationInfo securityInfo =  null;
5350         if (alias != null) {
5351             securityInfo = mPairingConfigManager.getSecurityInfoPairedDevice(alias);
5352         }
5353         if (securityInfo != null) {
5354             responseNanPairingVerificationRequest(data.first.getClientId(),
5355                     data.second.getSessionId(),
5356                     data.second.getPeerIdOrAddIfNew(peerId, peerDiscMacAddr), pairingId, alias,
5357                     true, securityInfo.mNpk, securityInfo.mAkm, securityInfo.mCipherSuite);
5358         } else {
5359             // If local cache is not found, reject the verification request.
5360             responseNanPairingVerificationRequest(data.first.getClientId(), discoverySessionId,
5361                     data.second.getPeerIdOrAddIfNew(peerId, peerDiscMacAddr), pairingId, alias,
5362                     false, null, 0, WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128);
5363         }
5364     }
5365 
onPairingConfirmReceivedLocal(int pairingId, boolean accept, int reason, int requestType, boolean enableCache, PairingSecurityAssociationInfo npksa)5366     private boolean onPairingConfirmReceivedLocal(int pairingId, boolean accept, int reason,
5367             int requestType, boolean enableCache, PairingSecurityAssociationInfo npksa) {
5368         PairingInfo info = mPairingRequest.get(pairingId);
5369         mPairingRequest.remove(pairingId);
5370         if (info == null) {
5371             return false;
5372         }
5373         WifiAwareClientState client = mClients.get(info.mClientId);
5374         if (client == null) {
5375             Log.e(TAG,
5376                     "onPairingConfirmReceivedLocal: no client exists for clientId="
5377                             + info.mClientId);
5378             return false;
5379         }
5380 
5381         WifiAwareDiscoverySessionState session = client.getSession(info.mSessionId);
5382         if (session == null) {
5383             Log.e(TAG, "onPairingConfirmReceivedLocal: no session exists for clientId="
5384                     + info.mClientId
5385                     + ", sessionId=" + info.mSessionId);
5386             return false;
5387         }
5388         session.onPairingConfirmReceived(info.mPeerId, accept, info.mAlias, requestType);
5389         if (accept) {
5390             if (enableCache && requestType == NAN_PAIRING_REQUEST_TYPE_SETUP) {
5391                 mPairingConfigManager.addPairedDeviceSecurityAssociation(
5392                         client.getCallingPackage(), info.mAlias, npksa);
5393             }
5394             return true;
5395         }
5396         if (mVerboseLoggingEnabled) {
5397             Log.v(TAG, "Pairing request reject, reason=" + reason);
5398         }
5399         return true;
5400     }
5401 
onBootstrappingRequestReceivedLocal(int discoverySessionId, int peerId, byte[] peerDiscMacAddr, int bootstrappingId, int method)5402     private void onBootstrappingRequestReceivedLocal(int discoverySessionId, int peerId,
5403             byte[] peerDiscMacAddr, int bootstrappingId, int method) {
5404         Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
5405                 getClientSessionForPubSubId(discoverySessionId);
5406         if (data == null) {
5407             Log.e(TAG, "onBootstrappingRequestReceivedLocal: no session found for pubSubId="
5408                     + discoverySessionId);
5409             return;
5410         }
5411         if (data.second.acceptsBootstrappingMethod(method)) {
5412             respondToBootstrappingRequest(data.first.getClientId(), data.second.getSessionId(),
5413                     data.second.getPeerIdOrAddIfNew(peerId, peerDiscMacAddr), bootstrappingId,
5414                     true, method);
5415         } else {
5416             respondToBootstrappingRequest(data.first.getClientId(), data.second.getSessionId(),
5417                     data.second.getPeerIdOrAddIfNew(peerId, peerDiscMacAddr), bootstrappingId,
5418                     false, method);
5419         }
5420     }
5421 
onBootStrappingConfirmReceivedLocal(int id, int reason, int responseCode, int comeBackDelay, byte[] cookie)5422     private boolean onBootStrappingConfirmReceivedLocal(int id, int reason, int responseCode,
5423             int comeBackDelay, byte[] cookie) {
5424         BootStrppingInfo info = mBootstrappingRequest.get(id);
5425         mBootstrappingRequest.remove(id);
5426         if (info == null) {
5427             return false;
5428         }
5429         if (responseCode == NAN_BOOTSTRAPPING_COMEBACK && comeBackDelay > 0) {
5430             if (!info.mIsComeBackFollowUp) {
5431                 initiateBootStrappingSetupRequest(info.mClientId, info.mSessionId, info.mPeerId,
5432                         info.mMethod, comeBackDelay * 1000L, cookie);
5433                 return true;
5434             }
5435             Log.e(TAG, "onBootStrappingConfirmReceivedLocal come back event on a"
5436                     + "comback followup request, handle it as reject!");
5437         }
5438         String methodString = "onBootStrappingConfirmReceivedLocal";
5439         WifiAwareDiscoverySessionState session = getClientSession(info.mClientId, info.mSessionId,
5440                 methodString);
5441         if (session == null) {
5442             return false;
5443         }
5444         boolean accept = responseCode == NAN_BOOTSTRAPPING_ACCEPT;
5445         session.onBootStrappingConfirmReceived(info.mPeerId, accept, info.mMethod);
5446 
5447         if (!accept && mVerboseLoggingEnabled) {
5448             Log.v(TAG, "bootstrapping request reject, reason=" + reason);
5449         }
5450         return true;
5451     }
5452 
onSuspensionModeChangedLocal(boolean isSuspended)5453     private void onSuspensionModeChangedLocal(boolean isSuspended) {
5454         if (isSuspended) return;
5455 
5456         // Trigger resume success callback for all suspended sessions when device exits
5457         // suspended mode.
5458         for (int i = 0; i < mClients.size(); i++) {
5459             WifiAwareClientState clientState = mClients.valueAt(i);
5460             SparseArray<WifiAwareDiscoverySessionState> sessions = clientState.getSessions();
5461             for (int j = 0; j < sessions.size(); j++) {
5462                 WifiAwareDiscoverySessionState session = sessions.valueAt(j);
5463                 if (session != null && session.isSessionSuspended()) {
5464                     session.onResumeSuccess();
5465                 }
5466             }
5467         }
5468     }
5469 
5470     /*
5471      * Utilities
5472      */
5473 
getClientSessionForPubSubId( int pubSubId)5474     private Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> getClientSessionForPubSubId(
5475             int pubSubId) {
5476         for (int i = 0; i < mClients.size(); ++i) {
5477             WifiAwareClientState client = mClients.valueAt(i);
5478             WifiAwareDiscoverySessionState session = client.getAwareSessionStateForPubSubId(
5479                     pubSubId);
5480             if (session != null) {
5481                 return new Pair<>(client, session);
5482             }
5483         }
5484 
5485         return null;
5486     }
5487 
5488     @Nullable
getClientSession(int clientId, int sessionId, String methodString)5489     private WifiAwareDiscoverySessionState getClientSession(int clientId, int sessionId,
5490             String methodString) {
5491         WifiAwareClientState client = mClients.get(clientId);
5492         if (client == null) {
5493             Log.e(
5494                     TAG,
5495                     methodString + ": no client exists for " + "clientId=" + clientId);
5496             return null;
5497         }
5498 
5499         WifiAwareDiscoverySessionState session = client.getSession(sessionId);
5500         if (session == null) {
5501             Log.e(TAG,
5502                     methodString + ": no session exists for "
5503                             + "clientId=" + clientId + ", sessionId=" + sessionId);
5504             return null;
5505         }
5506 
5507         return session;
5508     }
5509 
5510     /**
5511      * Merge all the existing client configurations with the (optional) input configuration request.
5512      * If the configurations are "incompatible" (rules in comment below) return a null.
5513      */
mergeConfigRequests(ConfigRequest configRequest)5514     private ConfigRequest mergeConfigRequests(ConfigRequest configRequest) {
5515         if (mVerboseLoggingEnabled) {
5516             Log.v(TAG, "mergeConfigRequests(): mClients=[" + mClients + "], configRequest="
5517                     + configRequest);
5518         }
5519 
5520         if (mClients.size() == 0 && configRequest == null) {
5521             Log.e(TAG, "mergeConfigRequests: invalid state - called with 0 clients registered!");
5522             return null;
5523         }
5524 
5525         // TODO: continue working on merge algorithm:
5526         // - if any request 5g: enable
5527         // - maximal master preference
5528         // - cluster range: must be identical
5529         // - if any request identity change: enable
5530         // - discovery window: minimum value if specified, 0 (disable) is considered an infinity
5531         boolean support5gBand = false;
5532         boolean support6gBand = false;
5533         int masterPreference = 0;
5534         boolean clusterIdValid = false;
5535         int clusterLow = 0;
5536         int clusterHigh = ConfigRequest.CLUSTER_ID_MAX;
5537         int[] discoveryWindowInterval =
5538                 {ConfigRequest.DW_INTERVAL_NOT_INIT, ConfigRequest.DW_INTERVAL_NOT_INIT};
5539         List<OuiKeyedData> vendorData = null;
5540         if (configRequest != null) {
5541             support5gBand = configRequest.mSupport5gBand;
5542             support6gBand = configRequest.mSupport6gBand;
5543             masterPreference = configRequest.mMasterPreference;
5544             clusterIdValid = true;
5545             clusterLow = configRequest.mClusterLow;
5546             clusterHigh = configRequest.mClusterHigh;
5547             discoveryWindowInterval = configRequest.mDiscoveryWindowInterval;
5548         }
5549         for (int i = 0; i < mClients.size(); ++i) {
5550             ConfigRequest cr = mClients.valueAt(i).getConfigRequest();
5551 
5552             // any request turns on 5G
5553             if (cr.mSupport5gBand) {
5554                 support5gBand = true;
5555             }
5556 
5557             // any request turns on 5G
5558             if (cr.mSupport6gBand) {
5559                 support6gBand = true;
5560             }
5561 
5562             // maximal master preference
5563             masterPreference = Math.max(masterPreference, cr.mMasterPreference);
5564 
5565             // cluster range must be the same across all config requests
5566             if (!clusterIdValid) {
5567                 clusterIdValid = true;
5568                 clusterLow = cr.mClusterLow;
5569                 clusterHigh = cr.mClusterHigh;
5570             } else {
5571                 if (clusterLow != cr.mClusterLow) return null;
5572                 if (clusterHigh != cr.mClusterHigh) return null;
5573             }
5574 
5575             for (int band = ConfigRequest.NAN_BAND_24GHZ; band <= ConfigRequest.NAN_BAND_5GHZ;
5576                     ++band) {
5577                 if (discoveryWindowInterval[band] == ConfigRequest.DW_INTERVAL_NOT_INIT) {
5578                     discoveryWindowInterval[band] = cr.mDiscoveryWindowInterval[band];
5579                 } else if (cr.mDiscoveryWindowInterval[band]
5580                         == ConfigRequest.DW_INTERVAL_NOT_INIT) {
5581                     // do nothing: keep my values
5582                 } else if (discoveryWindowInterval[band] == ConfigRequest.DW_DISABLE) {
5583                     discoveryWindowInterval[band] = cr.mDiscoveryWindowInterval[band];
5584                 } else if (cr.mDiscoveryWindowInterval[band] == ConfigRequest.DW_DISABLE) {
5585                     // do nothing: keep my values
5586                 } else {
5587                     discoveryWindowInterval[band] = Math.min(discoveryWindowInterval[band],
5588                             cr.mDiscoveryWindowInterval[band]);
5589                 }
5590             }
5591 
5592             if (SdkLevel.isAtLeastV() && !cr.getVendorData().isEmpty()) {
5593                 vendorData = cr.getVendorData();
5594             }
5595         }
5596         ConfigRequest.Builder builder = new ConfigRequest.Builder().setSupport5gBand(support5gBand)
5597                 .setMasterPreference(masterPreference).setClusterLow(clusterLow)
5598                 .setClusterHigh(clusterHigh);
5599         for (int band = ConfigRequest.NAN_BAND_24GHZ; band <= ConfigRequest.NAN_BAND_5GHZ; ++band) {
5600             if (discoveryWindowInterval[band] != ConfigRequest.DW_INTERVAL_NOT_INIT) {
5601                 builder.setDiscoveryWindowInterval(band, discoveryWindowInterval[band]);
5602             }
5603         }
5604         if (SdkLevel.isAtLeastV()) {
5605             // Always use the vendor data from the incoming ConfigRequest if provided.
5606             // Otherwise, use the most recent vendor data in the mClients list.
5607             if (configRequest != null && !configRequest.getVendorData().isEmpty()) {
5608                 vendorData = configRequest.getVendorData();
5609             }
5610             if (vendorData != null) {
5611                 builder.setVendorData(vendorData);
5612             }
5613         }
5614         return builder.build();
5615     }
5616 
createMergedRequestorWs()5617     private WorkSource createMergedRequestorWs() {
5618         if (mVerboseLoggingEnabled) {
5619             Log.v(TAG, "createMergedRequestorWs(): mClients=[" + mClients + "]");
5620         }
5621         WorkSource requestorWs = new WorkSource();
5622         boolean isOpportunistic = false;
5623         for (int i = 0; i < mClients.size(); ++i) {
5624             WifiAwareClientState clientState = mClients.valueAt(i);
5625             if (clientState.isAwareOffload()
5626                     || mOpportunisticSet.contains(clientState.getCallingPackage())) {
5627                 isOpportunistic = true;
5628             } else {
5629                 requestorWs.add(
5630                         new WorkSource(clientState.getUid(), clientState.getCallingPackage()));
5631             }
5632         }
5633         if (requestorWs.size() == 0 && isOpportunistic) {
5634             // All clients are opportunistic, use Wifi UID
5635             return new WorkSource(Process.WIFI_UID);
5636         }
5637         return requestorWs;
5638     }
5639 
doesAnyClientNeedIdentityChangeNotifications()5640     private boolean doesAnyClientNeedIdentityChangeNotifications() {
5641         for (int i = 0; i < mClients.size(); ++i) {
5642             if (mClients.valueAt(i).getNotifyIdentityChange()) {
5643                 return true;
5644             }
5645         }
5646         return false;
5647     }
5648 
doesAnyClientNeedRanging()5649     private boolean doesAnyClientNeedRanging() {
5650         for (int i = 0; i < mClients.size(); ++i) {
5651             if (mClients.valueAt(i).isRangingEnabled()) {
5652                 return true;
5653             }
5654         }
5655         return false;
5656     }
5657 
getInstantModeFromAllClients()5658     private int getInstantModeFromAllClients() {
5659         if (mOverrideInstantMode != INSTANT_MODE_DISABLED) {
5660             return mOverrideInstantMode;
5661         }
5662         int instantMode = INSTANT_MODE_DISABLED;
5663         for (int i = 0; i < mClients.size(); ++i) {
5664             int currentClient = mClients.valueAt(i).getInstantMode((long) mContext.getResources()
5665                     .getInteger(R.integer.config_wifiAwareInstantCommunicationModeDurationMillis));
5666             if (currentClient == INSTANT_MODE_5GHZ) {
5667                 return currentClient;
5668             }
5669             if (currentClient == INSTANT_MODE_24GHZ) {
5670                 instantMode = currentClient;
5671             }
5672         }
5673         return instantMode;
5674     }
5675 
5676     /**
5677      * Just a proxy to call {@link WifiAwareDataPathStateManager#createAllInterfaces()} for test.
5678      */
5679     @VisibleForTesting
createAllDataPathInterfaces()5680     public void createAllDataPathInterfaces() {
5681         mDataPathMgr.createAllInterfaces();
5682     }
5683 
5684     /**
5685      * Dump the internal state of the class.
5686      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)5687     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5688         pw.println("AwareStateManager:");
5689         pw.println("  mClients: [" + mClients + "]");
5690         pw.println("  mUsageEnabled: " + mUsageEnabled);
5691         pw.println("  mCapabilities: [" + mCapabilities + "]");
5692         pw.println("  mCurrentAwareConfiguration: " + mCurrentAwareConfiguration);
5693         pw.println("  mCurrentIdentityNotification: " + mCurrentIdentityNotification);
5694         pw.println("  mOpportunisticSet: " + mOpportunisticSet);
5695         for (int i = 0; i < mClients.size(); ++i) {
5696             mClients.valueAt(i).dump(fd, pw, args);
5697         }
5698         pw.println("  mSettableParameters: " + mSettableParameters);
5699         mSm.dump(fd, pw, args);
5700         mDataPathMgr.dump(fd, pw, args);
5701         mWifiAwareNativeApi.dump(fd, pw, args);
5702         pw.println("mAwareMetrics:");
5703         mAwareMetrics.dump(fd, pw, args);
5704     }
5705 
handleLocationModeDisabled()5706     private void handleLocationModeDisabled() {
5707         for (int i = 0; i < mClients.size(); i++) {
5708             WifiAwareClientState clientState = mClients.valueAt(i);
5709             if (SdkLevel.isAtLeastT()) {
5710                 try {
5711                     // As location mode is disabled, only app disavowal the location can pass the
5712                     // check.
5713                     mWifiPermissionsUtil.enforceNearbyDevicesPermission(
5714                             (AttributionSource) clientState.getAttributionSource(), true,
5715                             "Wifi Aware location mode change.");
5716                 } catch (SecurityException e) {
5717                     disconnect(clientState.getClientId());
5718                 }
5719             } else {
5720                 disconnect(clientState.getClientId());
5721             }
5722         }
5723     }
5724 
getAwareInstantCommunicationChannel(int instantMode)5725     private int getAwareInstantCommunicationChannel(int instantMode) {
5726         if (instantMode != INSTANT_MODE_5GHZ) {
5727             return AWARE_BAND_2_INSTANT_COMMUNICATION_CHANNEL_FREQ;
5728         }
5729         if (mAwareBand5InstantCommunicationChannelFreq == 0) {
5730             // If 5G instant communication doesn't have a valid channel, fallback to 2G.
5731             return AWARE_BAND_2_INSTANT_COMMUNICATION_CHANNEL_FREQ;
5732         }
5733         if (mAwareBand5InstantCommunicationChannelFreq > 0) {
5734             return mAwareBand5InstantCommunicationChannelFreq;
5735         }
5736         List<WifiAvailableChannel> channels = mWifiInjector.getWifiThreadRunner().call(
5737                 () -> mWifiInjector.getWifiNative().getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ,
5738                         OP_MODE_WIFI_AWARE, WifiAvailableChannel.FILTER_NAN_INSTANT_MODE), null,
5739                 TAG + "#getAwareInstantCommunicationChannel");
5740         if (channels == null || channels.isEmpty()) {
5741             if (mVerboseLoggingEnabled) {
5742                 Log.v(TAG, "No available instant communication mode channel");
5743             }
5744             mAwareBand5InstantCommunicationChannelFreq = 0;
5745         } else {
5746             if (channels.size() > 1) {
5747                 if (mVerboseLoggingEnabled) {
5748                     Log.v(TAG, "should have only one 5G instant communication channel,"
5749                             + "but size=" + channels.size());
5750                 }
5751             }
5752             // TODO(b/232138258): When the filter issue fixed, just check if only return channel is
5753             //  correct
5754             for (WifiAvailableChannel channel : channels) {
5755                 int freq = channel.getFrequencyMhz();
5756                 if (freq == AWARE_BAND_5_INSTANT_COMMUNICATION_CHANNEL_FREQ_CHANNEL_149) {
5757                     mAwareBand5InstantCommunicationChannelFreq =
5758                             AWARE_BAND_5_INSTANT_COMMUNICATION_CHANNEL_FREQ_CHANNEL_149;
5759                     break;
5760                 } else if (freq == AWARE_BAND_5_INSTANT_COMMUNICATION_CHANNEL_FREQ_CHANNEL_44) {
5761                     mAwareBand5InstantCommunicationChannelFreq =
5762                             AWARE_BAND_5_INSTANT_COMMUNICATION_CHANNEL_FREQ_CHANNEL_44;
5763                 }
5764             }
5765             if (mAwareBand5InstantCommunicationChannelFreq == -1) {
5766                 Log.e(TAG, "Both channel 149 and 44 are not available when the 5G WI-FI is "
5767                         + "supported");
5768                 mAwareBand5InstantCommunicationChannelFreq = 0;
5769             }
5770         }
5771         return mAwareBand5InstantCommunicationChannelFreq == 0
5772                 ? AWARE_BAND_2_INSTANT_COMMUNICATION_CHANNEL_FREQ
5773                 : mAwareBand5InstantCommunicationChannelFreq;
5774     }
5775 
isAwareOffloading()5776     private boolean isAwareOffloading() {
5777         for (int i = 0; i < mClients.size(); ++i) {
5778             WifiAwareClientState clientState = mClients.valueAt(i);
5779             if (clientState.isAwareOffload()) {
5780                 return true;
5781             }
5782         }
5783         return false;
5784     }
5785 
isAnyCallerIgnoringBatteryOptimizations()5786     private boolean isAnyCallerIgnoringBatteryOptimizations() {
5787         for (int i = 0; i < mClients.size(); ++i) {
5788             WifiAwareClientState clientState = mClients.valueAt(i);
5789             if (mPowerManager.isIgnoringBatteryOptimizations(clientState.getCallingPackage())) {
5790                 return true;
5791             }
5792         }
5793         return false;
5794     }
5795 
convertFrameworkHalCommandToEnum(int cmd)5796     private int convertFrameworkHalCommandToEnum(int cmd) {
5797         switch (cmd) {
5798             case COMMAND_TYPE_CONNECT:
5799                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_ENABLE_REQUEST;
5800             case COMMAND_TYPE_RECONFIGURE:
5801                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_CONFIG_REQUEST;
5802             case COMMAND_TYPE_DISABLE:
5803                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_DISABLE_REQUEST;
5804             case COMMAND_TYPE_PUBLISH:
5805             case COMMAND_TYPE_UPDATE_PUBLISH:
5806                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_START_PUBLISH_REQUEST;
5807             case COMMAND_TYPE_SUBSCRIBE:
5808             case COMMAND_TYPE_UPDATE_SUBSCRIBE:
5809                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_START_SUBSCRIBE_REQUEST;
5810             case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE:
5811                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_TRANSMIT_FOLLOW_UP_REQUEST;
5812             case COMMAND_TYPE_INITIATE_PAIRING_REQUEST:
5813                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_INITIATE_PAIRING_REQUEST;
5814             case COMMAND_TYPE_RESPONSE_PAIRING_REQUEST:
5815                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESPOND_TO_PAIRING_INDICATION_REQUEST;
5816             case COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST:
5817                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_INITIATE_BOOTSTRAPPING_REQUEST;
5818             case COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST:
5819                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESPOND_TO_BOOTSTRAPPING_INDICATION_REQUEST;
5820             case COMMAND_TYPE_GET_CAPABILITIES:
5821                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_GET_CAPABILITIES_REQUEST;
5822             case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE:
5823                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_CREATE_DATA_INTERFACE_REQUEST;
5824             case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE:
5825                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_DELETE_DATA_INTERFACE_REQUEST;
5826             case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP:
5827                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_INITIATE_DATA_PATH_REQUEST;
5828             case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST:
5829                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESPOND_TO_DATA_PATH_INDICATION_REQUEST;
5830             case COMMAND_TYPE_END_DATA_PATH:
5831                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_TERMINATE_DATA_PATH_REQUEST;
5832             case COMMAND_TYPE_END_PAIRING:
5833                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_TERMINATE_PAIRING_REQUEST;
5834             case COMMAND_TYPE_SUSPEND_SESSION:
5835                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_SUSPEND_REQUEST;
5836             case COMMAND_TYPE_RESUME_SESSION:
5837                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_RESUME_REQUEST;
5838             default:
5839                 return WIFI_AWARE_HAL_API_CALLED__COMMAND__AWARE_API_UNKNOWN;
5840         }
5841     }
5842 
recordHalApiCall(int command, int state, long starTime)5843     private void recordHalApiCall(int command, int state, long starTime) {
5844         WifiStatsLog.write(
5845                 WIFI_AWARE_HAL_API_CALLED,
5846                 convertFrameworkHalCommandToEnum(command),
5847                 convertNanStatusCodeToWifiStatsLogEnum(state),
5848                 (int) (SystemClock.elapsedRealtime() - starTime));
5849     }
5850 }
5851