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