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