blob: c2ae17c4bdeba902bc5429f438a49d810982f3ff [file] [log] [blame]
Etan Cohen20d329b2015-09-29 13:49:02 -07001/*
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
Etan Cohen0849ded2016-10-26 11:22:06 -070017package android.net.wifi.aware;
Etan Cohen20d329b2015-09-29 13:49:02 -070018
Etan Cohen85b1a5b2016-06-20 09:28:55 -070019import android.annotation.IntDef;
Etan Cohen5e680da2016-04-06 15:01:48 -070020import android.annotation.NonNull;
21import android.annotation.Nullable;
Roshan Piusd0f54752019-12-05 10:19:39 -080022import android.annotation.RequiresPermission;
Etan Cohen5f47bf22016-03-23 11:40:26 -070023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Etan Cohen88aa12b2017-11-08 08:41:39 -080025import android.annotation.SystemService;
Etan Cohen4503dc62016-08-11 09:31:21 -070026import android.content.Context;
Etan Cohenee58a682016-07-15 15:28:39 -070027import android.net.ConnectivityManager;
28import android.net.NetworkRequest;
Etan Cohen68507282017-03-30 08:54:39 -070029import android.net.NetworkSpecifier;
David Su5b62f3d2019-12-06 12:02:51 -080030import android.net.wifi.util.HexEncoding;
Etan Cohen20d329b2015-09-29 13:49:02 -070031import android.os.Binder;
Etan Cohene43df4d2018-02-22 15:54:20 -080032import android.os.Build;
Etan Cohen231859c2016-03-14 18:06:46 -070033import android.os.Bundle;
34import android.os.Handler;
Etan Cohen231859c2016-03-14 18:06:46 -070035import android.os.Looper;
36import android.os.Message;
Etan Cohen20d329b2015-09-29 13:49:02 -070037import android.os.RemoteException;
38import android.util.Log;
Etan Cohen51181fb2016-03-18 08:43:38 -070039
Etan Cohen85b1a5b2016-06-20 09:28:55 -070040import java.lang.annotation.Retention;
41import java.lang.annotation.RetentionPolicy;
Etan Cohen51181fb2016-03-18 08:43:38 -070042import java.lang.ref.WeakReference;
Etan Cohen1857b982016-11-23 11:11:23 -080043import java.nio.BufferOverflowException;
Etan Cohen1857b982016-11-23 11:11:23 -080044import java.util.List;
Etan Cohen51181fb2016-03-18 08:43:38 -070045
Etan Cohen20d329b2015-09-29 13:49:02 -070046/**
Etan Cohen0849ded2016-10-26 11:22:06 -070047 * This class provides the primary API for managing Wi-Fi Aware operations:
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060048 * discovery and peer-to-peer data connections.
Etan Cohen20d329b2015-09-29 13:49:02 -070049 * <p>
50 * The class provides access to:
51 * <ul>
Etan Cohen0849ded2016-10-26 11:22:06 -070052 * <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
Etan Cohen3de35a52016-12-19 15:54:51 -080053 * {@link #attach(AttachCallback, Handler)}.
Etan Cohen78ef40a2016-09-20 17:22:35 -070054 * <li>Create discovery sessions (publish or subscribe sessions). Refer to
Etan Cohen3de35a52016-12-19 15:54:51 -080055 * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} and
56 * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}.
Etan Cohen0849ded2016-10-26 11:22:06 -070057 * <li>Create a Aware network specifier to be used with
Etan Cohenb0214c42016-08-18 09:55:31 -070058 * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
Etan Cohen0ccb0c82019-03-10 18:09:17 -070059 * to set-up a Aware connection with a peer. Refer to {@link WifiAwareNetworkSpecifier.Builder}.
Etan Cohen20d329b2015-09-29 13:49:02 -070060 * </ul>
Etan Cohenb0214c42016-08-18 09:55:31 -070061 * <p>
Etan Cohen0849ded2016-10-26 11:22:06 -070062 * Aware may not be usable when Wi-Fi is disabled (and other conditions). To validate that
Etan Cohenb68ed282016-09-20 09:23:33 -070063 * the functionality is available use the {@link #isAvailable()} function. To track
Etan Cohen0849ded2016-10-26 11:22:06 -070064 * changes in Aware usability register for the {@link #ACTION_WIFI_AWARE_STATE_CHANGED}
65 * broadcast. Note that this broadcast is not sticky - you should register for it and then
66 * check the above API to avoid a race condition.
Etan Cohenb0214c42016-08-18 09:55:31 -070067 * <p>
Etan Cohen3de35a52016-12-19 15:54:51 -080068 * An application must use {@link #attach(AttachCallback, Handler)} to initialize a
Etan Cohen0849ded2016-10-26 11:22:06 -070069 * Aware cluster - before making any other Aware operation. Aware cluster membership is a
70 * device-wide operation - the API guarantees that the device is in a cluster or joins a
71 * Aware cluster (or starts one if none can be found). Information about attach success (or
Etan Cohen3de35a52016-12-19 15:54:51 -080072 * failure) are returned in callbacks of {@link AttachCallback}. Proceed with Aware
Etan Cohen0849ded2016-10-26 11:22:06 -070073 * discovery or connection setup only after receiving confirmation that Aware attach
Etan Cohen3de35a52016-12-19 15:54:51 -080074 * succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an
Etan Cohen0849ded2016-10-26 11:22:06 -070075 * application is finished using Aware it <b>must</b> use the
Etan Cohena1d90d92017-04-20 15:13:24 -070076 * {@link WifiAwareSession#close()} API to indicate to the Aware service that the device
Etan Cohen0849ded2016-10-26 11:22:06 -070077 * may detach from the Aware cluster. The device will actually disable Aware once the last
78 * application detaches.
Etan Cohenb0214c42016-08-18 09:55:31 -070079 * <p>
Etan Cohen0849ded2016-10-26 11:22:06 -070080 * Once a Aware attach is confirmed use the
Etan Cohen3de35a52016-12-19 15:54:51 -080081 * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
Etan Cohen0849ded2016-10-26 11:22:06 -070082 * or
Etan Cohen3de35a52016-12-19 15:54:51 -080083 * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
Etan Cohen6831f932016-11-16 13:40:55 -080084 * Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the
Etan Cohen3de35a52016-12-19 15:54:51 -080085 * provided callback object {@link DiscoverySessionCallback}. Specifically, the
86 * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}
Etan Cohen38553702016-09-14 14:41:56 -070087 * and
Etan Cohen3de35a52016-12-19 15:54:51 -080088 * {@link DiscoverySessionCallback#onSubscribeStarted(
89 *SubscribeDiscoverySession)}
90 * return {@link PublishDiscoverySession} and
91 * {@link SubscribeDiscoverySession}
Etan Cohen38553702016-09-14 14:41:56 -070092 * objects respectively on which additional session operations can be performed, e.g. updating
Etan Cohen3de35a52016-12-19 15:54:51 -080093 * the session {@link PublishDiscoverySession#updatePublish(PublishConfig)} and
94 * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
Etan Cohen0849ded2016-10-26 11:22:06 -070095 * also be used to send messages using the
Etan Cohen3de35a52016-12-19 15:54:51 -080096 * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an
Etan Cohen27c18cb2016-09-22 08:18:36 -070097 * application is finished with a discovery session it <b>must</b> terminate it using the
Etan Cohena1d90d92017-04-20 15:13:24 -070098 * {@link DiscoverySession#close()} API.
Etan Cohenb0214c42016-08-18 09:55:31 -070099 * <p>
Etan Cohen0849ded2016-10-26 11:22:06 -0700100 * Creating connections between Aware devices is managed by the standard
101 * {@link ConnectivityManager#requestNetwork(NetworkRequest,
102 * ConnectivityManager.NetworkCallback)}.
Etan Cohenb0214c42016-08-18 09:55:31 -0700103 * The {@link NetworkRequest} object should be constructed with:
104 * <ul>
105 * <li>{@link NetworkRequest.Builder#addTransportType(int)} of
Etan Cohen0849ded2016-10-26 11:22:06 -0700106 * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
Etan Cohenb0214c42016-08-18 09:55:31 -0700107 * <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
Etan Cohen0ccb0c82019-03-10 18:09:17 -0700108 * {@link WifiAwareNetworkSpecifier.Builder}.
Etan Cohenb0214c42016-08-18 09:55:31 -0700109 * </ul>
Etan Cohen20d329b2015-09-29 13:49:02 -0700110 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600111@SystemService(Context.WIFI_AWARE_SERVICE)
Etan Cohen0849ded2016-10-26 11:22:06 -0700112public class WifiAwareManager {
113 private static final String TAG = "WifiAwareManager";
Etan Cohen7d6c3892016-02-11 14:57:00 -0800114 private static final boolean DBG = false;
Etan Cohen20d329b2015-09-29 13:49:02 -0700115 private static final boolean VDBG = false; // STOPSHIP if true
116
Etan Cohen5f47bf22016-03-23 11:40:26 -0700117 /**
Etan Cohen0849ded2016-10-26 11:22:06 -0700118 * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
Etan Cohen93617992016-09-21 17:54:35 -0700119 * Use the {@link #isAvailable()} to query the current status.
120 * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
Etan Cohen0849ded2016-10-26 11:22:06 -0700121 * the broadcast to check the current state of Wi-Fi Aware.
Etan Cohen4c22e8b2016-09-29 16:02:30 -0700122 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
123 * components will be launched.
Etan Cohen5f47bf22016-03-23 11:40:26 -0700124 */
125 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
Etan Cohen0849ded2016-10-26 11:22:06 -0700126 public static final String ACTION_WIFI_AWARE_STATE_CHANGED =
127 "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
Etan Cohen5f47bf22016-03-23 11:40:26 -0700128
Etan Cohenb0214c42016-08-18 09:55:31 -0700129 /** @hide */
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700130 @IntDef({
Etan Cohen0849ded2016-10-26 11:22:06 -0700131 WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, WIFI_AWARE_DATA_PATH_ROLE_RESPONDER})
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700132 @Retention(RetentionPolicy.SOURCE)
133 public @interface DataPathRole {
134 }
135
136 /**
Etan Cohenb0214c42016-08-18 09:55:31 -0700137 * Connection creation role is that of INITIATOR. Used to create a network specifier string
Etan Cohen0849ded2016-10-26 11:22:06 -0700138 * when requesting a Aware network.
Etan Cohenb0214c42016-08-18 09:55:31 -0700139 *
Etan Cohen3a764c12017-03-08 09:05:02 -0800140 * @see WifiAwareSession#createNetworkSpecifierOpen(int, byte[])
141 * @see WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700142 */
Etan Cohen0849ded2016-10-26 11:22:06 -0700143 public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700144
145 /**
Etan Cohenb0214c42016-08-18 09:55:31 -0700146 * Connection creation role is that of RESPONDER. Used to create a network specifier string
Etan Cohen0849ded2016-10-26 11:22:06 -0700147 * when requesting a Aware network.
Etan Cohenb0214c42016-08-18 09:55:31 -0700148 *
Etan Cohen3a764c12017-03-08 09:05:02 -0800149 * @see WifiAwareSession#createNetworkSpecifierOpen(int, byte[])
150 * @see WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700151 */
Etan Cohen0849ded2016-10-26 11:22:06 -0700152 public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700153
Etan Cohen4503dc62016-08-11 09:31:21 -0700154 private final Context mContext;
Etan Cohen0849ded2016-10-26 11:22:06 -0700155 private final IWifiAwareManager mService;
Etan Cohen51181fb2016-03-18 08:43:38 -0700156
Etan Cohen447b0322016-05-09 15:30:06 -0700157 private final Object mLock = new Object(); // lock access to the following vars
Etan Cohen51181fb2016-03-18 08:43:38 -0700158
Etan Cohenb0214c42016-08-18 09:55:31 -0700159 /** @hide */
David Su409f3712019-10-24 11:18:41 -0700160 public WifiAwareManager(@NonNull Context context, @NonNull IWifiAwareManager service) {
Etan Cohen4503dc62016-08-11 09:31:21 -0700161 mContext = context;
Etan Cohen20d329b2015-09-29 13:49:02 -0700162 mService = service;
163 }
164
165 /**
Etan Cohen0849ded2016-10-26 11:22:06 -0700166 * Returns the current status of Aware API: whether or not Aware is available. To track
167 * changes in the state of Aware API register for the
168 * {@link #ACTION_WIFI_AWARE_STATE_CHANGED} broadcast.
Etan Cohen5f47bf22016-03-23 11:40:26 -0700169 *
Etan Cohen0849ded2016-10-26 11:22:06 -0700170 * @return A boolean indicating whether the app can use the Aware API at this time (true) or
Etan Cohenb68ed282016-09-20 09:23:33 -0700171 * not (false).
Etan Cohen5f47bf22016-03-23 11:40:26 -0700172 */
Etan Cohenb68ed282016-09-20 09:23:33 -0700173 public boolean isAvailable() {
Etan Cohen5f47bf22016-03-23 11:40:26 -0700174 try {
175 return mService.isUsageEnabled();
176 } catch (RemoteException e) {
Etan Cohenfc3c0a02016-08-16 11:54:49 -0700177 throw e.rethrowFromSystemServer();
Etan Cohen5f47bf22016-03-23 11:40:26 -0700178 }
Etan Cohen5f47bf22016-03-23 11:40:26 -0700179 }
180
181 /**
Etan Cohen0849ded2016-10-26 11:22:06 -0700182 * Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify
Etan Cohene64c62f2016-10-03 15:14:51 -0700183 * limitations on configurations, e.g. the maximum service name length.
184 *
Etan Cohen0849ded2016-10-26 11:22:06 -0700185 * @return An object specifying configuration limitations of Aware.
Etan Cohene64c62f2016-10-03 15:14:51 -0700186 */
Etan Cohen3de35a52016-12-19 15:54:51 -0800187 public Characteristics getCharacteristics() {
Etan Cohene64c62f2016-10-03 15:14:51 -0700188 try {
189 return mService.getCharacteristics();
190 } catch (RemoteException e) {
191 throw e.rethrowFromSystemServer();
192 }
193 }
194
195 /**
Etan Cohen0849ded2016-10-26 11:22:06 -0700196 * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
Etan Cohen78ef40a2016-09-20 17:22:35 -0700197 * create connections to peers. The device will attach to an existing cluster if it can find
Etan Cohen0849ded2016-10-26 11:22:06 -0700198 * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
Etan Cohen78ef40a2016-09-20 17:22:35 -0700199 * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
Etan Cohena1d90d92017-04-20 15:13:24 -0700200 * An application <b>must</b> call {@link WifiAwareSession#close()} when done with the
Etan Cohen0849ded2016-10-26 11:22:06 -0700201 * Wi-Fi Aware object.
Etan Cohenb0214c42016-08-18 09:55:31 -0700202 * <p>
Etan Cohen0849ded2016-10-26 11:22:06 -0700203 * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster
Etan Cohen78ef40a2016-09-20 17:22:35 -0700204 * then this function will simply indicate success immediately using the same {@code
205 * attachCallback}.
Etan Cohen20d329b2015-09-29 13:49:02 -0700206 *
Etan Cohen6831f932016-11-16 13:40:55 -0800207 * @param attachCallback A callback for attach events, extended from
Etan Cohen3de35a52016-12-19 15:54:51 -0800208 * {@link AttachCallback}.
Etan Cohenede1d0f2016-09-21 11:18:35 -0700209 * @param handler The Handler on whose thread to execute the callbacks of the {@code
210 * attachCallback} object. If a null is provided then the application's main thread will be
211 * used.
Etan Cohen20d329b2015-09-29 13:49:02 -0700212 */
Etan Cohen3de35a52016-12-19 15:54:51 -0800213 public void attach(@NonNull AttachCallback attachCallback, @Nullable Handler handler) {
Etan Cohen78ef40a2016-09-20 17:22:35 -0700214 attach(handler, null, attachCallback, null);
Etan Cohen51181fb2016-03-18 08:43:38 -0700215 }
Etan Cohen231859c2016-03-14 18:06:46 -0700216
Etan Cohen51181fb2016-03-18 08:43:38 -0700217 /**
Etan Cohen0849ded2016-10-26 11:22:06 -0700218 * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
Etan Cohen78ef40a2016-09-20 17:22:35 -0700219 * create connections to peers. The device will attach to an existing cluster if it can find
Etan Cohen0849ded2016-10-26 11:22:06 -0700220 * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
Etan Cohen78ef40a2016-09-20 17:22:35 -0700221 * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
Etan Cohena1d90d92017-04-20 15:13:24 -0700222 * An application <b>must</b> call {@link WifiAwareSession#close()} when done with the
Etan Cohen0849ded2016-10-26 11:22:06 -0700223 * Wi-Fi Aware object.
Etan Cohenb0214c42016-08-18 09:55:31 -0700224 * <p>
Etan Cohen0849ded2016-10-26 11:22:06 -0700225 * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster
Etan Cohen78ef40a2016-09-20 17:22:35 -0700226 * then this function will simply indicate success immediately using the same {@code
227 * attachCallback}.
228 * <p>
Etan Cohen0849ded2016-10-26 11:22:06 -0700229 * This version of the API attaches a listener to receive the MAC address of the Aware interface
Etan Cohen78ef40a2016-09-20 17:22:35 -0700230 * on startup and whenever it is updated (it is randomized at regular intervals for privacy).
Etan Cohen12f70532019-01-23 09:01:46 -0800231 * The application must have the {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
Etan Cohen78ef40a2016-09-20 17:22:35 -0700232 * permission to execute this attach request. Otherwise, use the
Etan Cohen3de35a52016-12-19 15:54:51 -0800233 * {@link #attach(AttachCallback, Handler)} version. Note that aside from permission
Etan Cohen78ef40a2016-09-20 17:22:35 -0700234 * requirements this listener will wake up the host at regular intervals causing higher power
235 * consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
Etan Cohen51181fb2016-03-18 08:43:38 -0700236 *
Etan Cohen78ef40a2016-09-20 17:22:35 -0700237 * @param attachCallback A callback for attach events, extended from
Etan Cohen3de35a52016-12-19 15:54:51 -0800238 * {@link AttachCallback}.
Etan Cohenede1d0f2016-09-21 11:18:35 -0700239 * @param identityChangedListener A listener for changed identity, extended from
Etan Cohen3de35a52016-12-19 15:54:51 -0800240 * {@link IdentityChangedListener}.
Etan Cohen6831f932016-11-16 13:40:55 -0800241 * @param handler The Handler on whose thread to execute the callbacks of the {@code
242 * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
243 * application's main thread will be used.
Etan Cohen51181fb2016-03-18 08:43:38 -0700244 */
Etan Cohen3de35a52016-12-19 15:54:51 -0800245 public void attach(@NonNull AttachCallback attachCallback,
246 @NonNull IdentityChangedListener identityChangedListener,
Etan Cohen6831f932016-11-16 13:40:55 -0800247 @Nullable Handler handler) {
Etan Cohen78ef40a2016-09-20 17:22:35 -0700248 attach(handler, null, attachCallback, identityChangedListener);
249 }
250
251 /** @hide */
252 public void attach(Handler handler, ConfigRequest configRequest,
Etan Cohen3de35a52016-12-19 15:54:51 -0800253 AttachCallback attachCallback,
254 IdentityChangedListener identityChangedListener) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700255 if (VDBG) {
Etan Cohen78ef40a2016-09-20 17:22:35 -0700256 Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback
257 + ", configRequest=" + configRequest + ", identityChangedListener="
258 + identityChangedListener);
Etan Cohen231859c2016-03-14 18:06:46 -0700259 }
260
Etan Cohenb7abd812018-01-04 07:34:50 -0800261 if (attachCallback == null) {
262 throw new IllegalArgumentException("Null callback provided");
263 }
264
Etan Cohen51181fb2016-03-18 08:43:38 -0700265 synchronized (mLock) {
Etan Cohenbd4bf352016-09-15 12:15:10 -0700266 Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
Etan Cohen231859c2016-03-14 18:06:46 -0700267
Etan Cohen51181fb2016-03-18 08:43:38 -0700268 try {
Etan Cohenbd4bf352016-09-15 12:15:10 -0700269 Binder binder = new Binder();
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800270 mService.connect(binder, mContext.getOpPackageName(), mContext.getAttributionTag(),
Etan Cohen0849ded2016-10-26 11:22:06 -0700271 new WifiAwareEventCallbackProxy(this, looper, binder, attachCallback,
Etan Cohen78ef40a2016-09-20 17:22:35 -0700272 identityChangedListener), configRequest,
273 identityChangedListener != null);
Etan Cohen51181fb2016-03-18 08:43:38 -0700274 } catch (RemoteException e) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700275 throw e.rethrowFromSystemServer();
276 }
Etan Cohen20d329b2015-09-29 13:49:02 -0700277 }
278 }
279
Etan Cohenbd4bf352016-09-15 12:15:10 -0700280 /** @hide */
281 public void disconnect(int clientId, Binder binder) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700282 if (VDBG) Log.v(TAG, "disconnect()");
283
Etan Cohen51181fb2016-03-18 08:43:38 -0700284 try {
285 mService.disconnect(clientId, binder);
Etan Cohen20d329b2015-09-29 13:49:02 -0700286 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700287 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700288 }
289 }
290
Etan Cohenb0214c42016-08-18 09:55:31 -0700291 /** @hide */
Etan Cohenbd4bf352016-09-15 12:15:10 -0700292 public void publish(int clientId, Looper looper, PublishConfig publishConfig,
Etan Cohen3de35a52016-12-19 15:54:51 -0800293 DiscoverySessionCallback callback) {
Etan Cohenbd4bf352016-09-15 12:15:10 -0700294 if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig);
Etan Cohen231859c2016-03-14 18:06:46 -0700295
Etan Cohenb7abd812018-01-04 07:34:50 -0800296 if (callback == null) {
297 throw new IllegalArgumentException("Null callback provided");
298 }
299
Etan Cohen20d329b2015-09-29 13:49:02 -0700300 try {
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800301 mService.publish(mContext.getOpPackageName(), mContext.getAttributionTag(), clientId,
Philip P. Moltmanndcb850c2019-10-04 08:14:38 -0700302 publishConfig,
Etan Cohen0849ded2016-10-26 11:22:06 -0700303 new WifiAwareDiscoverySessionCallbackProxy(this, looper, true, callback,
Etan Cohenbd4bf352016-09-15 12:15:10 -0700304 clientId));
Etan Cohen20d329b2015-09-29 13:49:02 -0700305 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700306 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700307 }
Etan Cohen20d329b2015-09-29 13:49:02 -0700308 }
309
Etan Cohenb0214c42016-08-18 09:55:31 -0700310 /** @hide */
Etan Cohenbd4bf352016-09-15 12:15:10 -0700311 public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) {
312 if (VDBG) {
313 Log.v(TAG, "updatePublish(): clientId=" + clientId + ",sessionId=" + sessionId
314 + ", config=" + publishConfig);
Etan Cohen51181fb2016-03-18 08:43:38 -0700315 }
Etan Cohenbd4bf352016-09-15 12:15:10 -0700316
Etan Cohen20d329b2015-09-29 13:49:02 -0700317 try {
Etan Cohen51181fb2016-03-18 08:43:38 -0700318 mService.updatePublish(clientId, sessionId, publishConfig);
Etan Cohen20d329b2015-09-29 13:49:02 -0700319 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700320 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700321 }
322 }
Etan Cohenb29bbcc2016-02-17 14:25:41 -0800323
Etan Cohenbd4bf352016-09-15 12:15:10 -0700324 /** @hide */
325 public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig,
Etan Cohen3de35a52016-12-19 15:54:51 -0800326 DiscoverySessionCallback callback) {
Etan Cohen20d329b2015-09-29 13:49:02 -0700327 if (VDBG) {
Etan Cohenbd4bf352016-09-15 12:15:10 -0700328 if (VDBG) {
329 Log.v(TAG,
330 "subscribe(): clientId=" + clientId + ", config=" + subscribeConfig);
Etan Cohen51181fb2016-03-18 08:43:38 -0700331 }
Etan Cohen231859c2016-03-14 18:06:46 -0700332 }
Etan Cohen20d329b2015-09-29 13:49:02 -0700333
Etan Cohenb7abd812018-01-04 07:34:50 -0800334 if (callback == null) {
335 throw new IllegalArgumentException("Null callback provided");
336 }
337
Etan Cohen20d329b2015-09-29 13:49:02 -0700338 try {
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800339 mService.subscribe(mContext.getOpPackageName(), mContext.getAttributionTag(), clientId,
Philip P. Moltmanndcb850c2019-10-04 08:14:38 -0700340 subscribeConfig,
Etan Cohen0849ded2016-10-26 11:22:06 -0700341 new WifiAwareDiscoverySessionCallbackProxy(this, looper, false, callback,
Etan Cohenbd4bf352016-09-15 12:15:10 -0700342 clientId));
Etan Cohen20d329b2015-09-29 13:49:02 -0700343 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700344 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700345 }
Etan Cohen20d329b2015-09-29 13:49:02 -0700346 }
347
Etan Cohenb0214c42016-08-18 09:55:31 -0700348 /** @hide */
Etan Cohenbd4bf352016-09-15 12:15:10 -0700349 public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) {
Etan Cohen20d329b2015-09-29 13:49:02 -0700350 if (VDBG) {
Etan Cohenbd4bf352016-09-15 12:15:10 -0700351 Log.v(TAG, "updateSubscribe(): clientId=" + clientId + ",sessionId=" + sessionId
352 + ", config=" + subscribeConfig);
Etan Cohen20d329b2015-09-29 13:49:02 -0700353 }
354
355 try {
Etan Cohen51181fb2016-03-18 08:43:38 -0700356 mService.updateSubscribe(clientId, sessionId, subscribeConfig);
Etan Cohen20d329b2015-09-29 13:49:02 -0700357 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700358 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700359 }
360 }
361
Etan Cohenb0214c42016-08-18 09:55:31 -0700362 /** @hide */
Etan Cohenbd4bf352016-09-15 12:15:10 -0700363 public void terminateSession(int clientId, int sessionId) {
364 if (VDBG) {
365 Log.d(TAG,
366 "terminateSession(): clientId=" + clientId + ", sessionId=" + sessionId);
Etan Cohen51181fb2016-03-18 08:43:38 -0700367 }
368
Etan Cohen20d329b2015-09-29 13:49:02 -0700369 try {
Etan Cohen51181fb2016-03-18 08:43:38 -0700370 mService.terminateSession(clientId, sessionId);
Etan Cohen20d329b2015-09-29 13:49:02 -0700371 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700372 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700373 }
374 }
375
Etan Cohenb0214c42016-08-18 09:55:31 -0700376 /** @hide */
Etan Cohen6831f932016-11-16 13:40:55 -0800377 public void sendMessage(int clientId, int sessionId, PeerHandle peerHandle, byte[] message,
Etan Cohen27c18cb2016-09-22 08:18:36 -0700378 int messageId, int retryCount) {
Etan Cohenf085c192016-09-27 09:15:46 -0700379 if (peerHandle == null) {
380 throw new IllegalArgumentException(
381 "sendMessage: invalid peerHandle - must be non-null");
382 }
383
Etan Cohen51181fb2016-03-18 08:43:38 -0700384 if (VDBG) {
Etan Cohen27c18cb2016-09-22 08:18:36 -0700385 Log.v(TAG, "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId
Etan Cohen6831f932016-11-16 13:40:55 -0800386 + ", peerHandle=" + peerHandle.peerId + ", messageId="
Etan Cohenf085c192016-09-27 09:15:46 -0700387 + messageId + ", retryCount=" + retryCount);
Etan Cohen51181fb2016-03-18 08:43:38 -0700388 }
389
390 try {
Etan Cohen6831f932016-11-16 13:40:55 -0800391 mService.sendMessage(clientId, sessionId, peerHandle.peerId, message, messageId,
392 retryCount);
Etan Cohen20d329b2015-09-29 13:49:02 -0700393 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700394 throw e.rethrowFromSystemServer();
Etan Cohen20d329b2015-09-29 13:49:02 -0700395 }
396 }
Etan Cohen231859c2016-03-14 18:06:46 -0700397
Etan Cohenb0214c42016-08-18 09:55:31 -0700398 /** @hide */
Roshan Piusd0f54752019-12-05 10:19:39 -0800399 @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
400 public void requestMacAddresses(int uid, List<Integer> peerIds,
401 IWifiAwareMacAddressProvider callback) {
402 try {
403 mService.requestMacAddresses(uid, peerIds, callback);
404 } catch (RemoteException e) {
405 throw e.rethrowFromSystemServer();
406 }
407 }
408
409 /** @hide */
Etan Cohen68507282017-03-30 08:54:39 -0700410 public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
Etan Cohen9b78f822018-01-19 17:21:06 -0800411 @NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700412 if (VDBG) {
413 Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
Etan Cohen6831f932016-11-16 13:40:55 -0800414 + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
Etan Cohen62a2f9f2017-02-21 10:08:42 -0800415 + ", pmk=" + ((pmk == null) ? "null" : "non-null")
416 + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700417 }
418
Etan Cohen8690e5d2018-11-27 07:33:43 -0800419 if (!WifiAwareUtils.isLegacyVersion(mContext, Build.VERSION_CODES.Q)) {
420 throw new UnsupportedOperationException(
Etan Cohen09231fb2019-04-06 10:21:37 -0700421 "API deprecated - use WifiAwareNetworkSpecifier.Builder");
Etan Cohen8690e5d2018-11-27 07:33:43 -0800422 }
423
Etan Cohen0849ded2016-10-26 11:22:06 -0700424 if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
425 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700426 throw new IllegalArgumentException(
427 "createNetworkSpecifier: Invalid 'role' argument when creating a network "
428 + "specifier");
429 }
Etan Cohene43df4d2018-02-22 15:54:20 -0800430 if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR || !WifiAwareUtils.isLegacyVersion(mContext,
431 Build.VERSION_CODES.P)) {
432 if (peerHandle == null) {
433 throw new IllegalArgumentException(
434 "createNetworkSpecifier: Invalid peer handle - cannot be null");
435 }
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700436 }
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700437
Etan Cohen68507282017-03-30 08:54:39 -0700438 return new WifiAwareNetworkSpecifier(
439 (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
440 : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB,
441 role,
442 clientId,
443 sessionId,
444 peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
445 null, // peerMac (not used in this method)
446 pmk,
Etan Cohen859748f2017-04-03 17:42:34 -0700447 passphrase,
Etan Cohen7faa4fa2018-10-17 15:48:39 -0700448 0, // no port info for deprecated IB APIs
Roshan Piuscb3d6522020-01-16 12:53:01 -0800449 -1); // no transport info for deprecated IB APIs
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700450 }
451
Etan Cohenbd4bf352016-09-15 12:15:10 -0700452 /** @hide */
Etan Cohen68507282017-03-30 08:54:39 -0700453 public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
Etan Cohen9b78f822018-01-19 17:21:06 -0800454 @NonNull byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700455 if (VDBG) {
Etan Cohen954111a2017-02-21 10:08:42 -0800456 Log.v(TAG, "createNetworkSpecifier: role=" + role
Etan Cohen62a2f9f2017-02-21 10:08:42 -0800457 + ", pmk=" + ((pmk == null) ? "null" : "non-null")
458 + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700459 }
460
Etan Cohen0849ded2016-10-26 11:22:06 -0700461 if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
462 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700463 throw new IllegalArgumentException(
464 "createNetworkSpecifier: Invalid 'role' argument when creating a network "
465 + "specifier");
466 }
Etan Cohene43df4d2018-02-22 15:54:20 -0800467 if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR || !WifiAwareUtils.isLegacyVersion(mContext,
468 Build.VERSION_CODES.P)) {
469 if (peer == null) {
470 throw new IllegalArgumentException(
471 "createNetworkSpecifier: Invalid peer MAC - cannot be null");
472 }
Etan Cohen954111a2017-02-21 10:08:42 -0800473 }
474 if (peer != null && peer.length != 6) {
475 throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700476 }
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700477
Etan Cohen68507282017-03-30 08:54:39 -0700478 return new WifiAwareNetworkSpecifier(
479 (peer == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER
480 : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
481 role,
482 clientId,
483 0, // 0 is an invalid session ID
484 0, // 0 is an invalid peer ID
485 peer,
486 pmk,
Etan Cohen859748f2017-04-03 17:42:34 -0700487 passphrase,
Etan Cohen7faa4fa2018-10-17 15:48:39 -0700488 0, // no port info for OOB APIs
Roshan Piuscb3d6522020-01-16 12:53:01 -0800489 -1); // no transport protocol info for OOB APIs
Etan Cohen85b1a5b2016-06-20 09:28:55 -0700490 }
491
Etan Cohen0849ded2016-10-26 11:22:06 -0700492 private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
Etan Cohen51181fb2016-03-18 08:43:38 -0700493 private static final int CALLBACK_CONNECT_SUCCESS = 0;
494 private static final int CALLBACK_CONNECT_FAIL = 1;
Etan Cohen271c0372016-05-06 08:57:56 -0700495 private static final int CALLBACK_IDENTITY_CHANGED = 2;
Etan Cohen231859c2016-03-14 18:06:46 -0700496
Etan Cohen231859c2016-03-14 18:06:46 -0700497 private final Handler mHandler;
Etan Cohen0849ded2016-10-26 11:22:06 -0700498 private final WeakReference<WifiAwareManager> mAwareManager;
Etan Cohenbd4bf352016-09-15 12:15:10 -0700499 private final Binder mBinder;
500 private final Looper mLooper;
Etan Cohen447b0322016-05-09 15:30:06 -0700501
Etan Cohen231859c2016-03-14 18:06:46 -0700502 /**
Etan Cohen3de35a52016-12-19 15:54:51 -0800503 * Constructs a {@link AttachCallback} using the specified looper.
Etan Cohenb0214c42016-08-18 09:55:31 -0700504 * All callbacks will delivered on the thread of the specified looper.
Etan Cohen231859c2016-03-14 18:06:46 -0700505 *
506 * @param looper The looper on which to execute the callbacks.
507 */
Etan Cohen0849ded2016-10-26 11:22:06 -0700508 WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder,
Etan Cohen3de35a52016-12-19 15:54:51 -0800509 final AttachCallback attachCallback,
510 final IdentityChangedListener identityChangedListener) {
Etan Cohen0849ded2016-10-26 11:22:06 -0700511 mAwareManager = new WeakReference<>(mgr);
Etan Cohenbd4bf352016-09-15 12:15:10 -0700512 mLooper = looper;
513 mBinder = binder;
Etan Cohen231859c2016-03-14 18:06:46 -0700514
Etan Cohen0849ded2016-10-26 11:22:06 -0700515 if (VDBG) Log.v(TAG, "WifiAwareEventCallbackProxy ctor: looper=" + looper);
Etan Cohen231859c2016-03-14 18:06:46 -0700516 mHandler = new Handler(looper) {
517 @Override
518 public void handleMessage(Message msg) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700519 if (DBG) {
Etan Cohen0849ded2016-10-26 11:22:06 -0700520 Log.d(TAG, "WifiAwareEventCallbackProxy: What=" + msg.what + ", msg="
521 + msg);
Etan Cohen51181fb2016-03-18 08:43:38 -0700522 }
523
Etan Cohen0849ded2016-10-26 11:22:06 -0700524 WifiAwareManager mgr = mAwareManager.get();
Etan Cohen51181fb2016-03-18 08:43:38 -0700525 if (mgr == null) {
Etan Cohen0849ded2016-10-26 11:22:06 -0700526 Log.w(TAG, "WifiAwareEventCallbackProxy: handleMessage post GC");
Etan Cohen51181fb2016-03-18 08:43:38 -0700527 return;
528 }
529
Etan Cohen231859c2016-03-14 18:06:46 -0700530 switch (msg.what) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700531 case CALLBACK_CONNECT_SUCCESS:
Etan Cohen78ef40a2016-09-20 17:22:35 -0700532 attachCallback.onAttached(
Etan Cohen0849ded2016-10-26 11:22:06 -0700533 new WifiAwareSession(mgr, mBinder, msg.arg1));
Etan Cohen231859c2016-03-14 18:06:46 -0700534 break;
Etan Cohen51181fb2016-03-18 08:43:38 -0700535 case CALLBACK_CONNECT_FAIL:
Etan Cohen0849ded2016-10-26 11:22:06 -0700536 mAwareManager.clear();
Etan Cohen5542ccc2016-09-21 14:37:02 -0700537 attachCallback.onAttachFailed();
Etan Cohen231859c2016-03-14 18:06:46 -0700538 break;
Etan Cohen231859c2016-03-14 18:06:46 -0700539 case CALLBACK_IDENTITY_CHANGED:
Etan Cohen275f3232017-01-30 13:01:50 -0800540 if (identityChangedListener == null) {
541 Log.e(TAG, "CALLBACK_IDENTITY_CHANGED: null listener.");
542 } else {
543 identityChangedListener.onIdentityChanged((byte[]) msg.obj);
544 }
Etan Cohen231859c2016-03-14 18:06:46 -0700545 break;
546 }
547 }
548 };
549 }
550
551 @Override
Etan Cohenbd4bf352016-09-15 12:15:10 -0700552 public void onConnectSuccess(int clientId) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700553 if (VDBG) Log.v(TAG, "onConnectSuccess");
Etan Cohen231859c2016-03-14 18:06:46 -0700554
Etan Cohen51181fb2016-03-18 08:43:38 -0700555 Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_SUCCESS);
Etan Cohenbd4bf352016-09-15 12:15:10 -0700556 msg.arg1 = clientId;
Etan Cohen231859c2016-03-14 18:06:46 -0700557 mHandler.sendMessage(msg);
558 }
559
560 @Override
Etan Cohen51181fb2016-03-18 08:43:38 -0700561 public void onConnectFail(int reason) {
Etan Cohen41d6f372016-09-22 11:00:57 -0700562 if (VDBG) Log.v(TAG, "onConnectFail: reason=" + reason);
Etan Cohen231859c2016-03-14 18:06:46 -0700563
Etan Cohen51181fb2016-03-18 08:43:38 -0700564 Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_FAIL);
Etan Cohen231859c2016-03-14 18:06:46 -0700565 msg.arg1 = reason;
Etan Cohen231859c2016-03-14 18:06:46 -0700566 mHandler.sendMessage(msg);
567 }
568
569 @Override
Etan Cohen2d3face2016-07-07 15:07:38 -0700570 public void onIdentityChanged(byte[] mac) {
571 if (VDBG) Log.v(TAG, "onIdentityChanged: mac=" + new String(HexEncoding.encode(mac)));
Etan Cohen231859c2016-03-14 18:06:46 -0700572
573 Message msg = mHandler.obtainMessage(CALLBACK_IDENTITY_CHANGED);
Etan Cohen2d3face2016-07-07 15:07:38 -0700574 msg.obj = mac;
Etan Cohen231859c2016-03-14 18:06:46 -0700575 mHandler.sendMessage(msg);
576 }
577 }
578
Etan Cohen0849ded2016-10-26 11:22:06 -0700579 private static class WifiAwareDiscoverySessionCallbackProxy extends
580 IWifiAwareDiscoverySessionCallback.Stub {
Etan Cohen231859c2016-03-14 18:06:46 -0700581 private static final int CALLBACK_SESSION_STARTED = 0;
Etan Cohen51181fb2016-03-18 08:43:38 -0700582 private static final int CALLBACK_SESSION_CONFIG_SUCCESS = 1;
583 private static final int CALLBACK_SESSION_CONFIG_FAIL = 2;
584 private static final int CALLBACK_SESSION_TERMINATED = 3;
585 private static final int CALLBACK_MATCH = 4;
586 private static final int CALLBACK_MESSAGE_SEND_SUCCESS = 5;
587 private static final int CALLBACK_MESSAGE_SEND_FAIL = 6;
588 private static final int CALLBACK_MESSAGE_RECEIVED = 7;
Etan Cohen88aa12b2017-11-08 08:41:39 -0800589 private static final int CALLBACK_MATCH_WITH_DISTANCE = 8;
Etan Cohen231859c2016-03-14 18:06:46 -0700590
Etan Cohen231859c2016-03-14 18:06:46 -0700591 private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
592 private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
593
Etan Cohen0849ded2016-10-26 11:22:06 -0700594 private final WeakReference<WifiAwareManager> mAwareManager;
Etan Cohen231859c2016-03-14 18:06:46 -0700595 private final boolean mIsPublish;
Etan Cohen3de35a52016-12-19 15:54:51 -0800596 private final DiscoverySessionCallback mOriginalCallback;
Etan Cohenbd4bf352016-09-15 12:15:10 -0700597 private final int mClientId;
Etan Cohen231859c2016-03-14 18:06:46 -0700598
599 private final Handler mHandler;
Etan Cohen3de35a52016-12-19 15:54:51 -0800600 private DiscoverySession mSession;
Etan Cohen231859c2016-03-14 18:06:46 -0700601
Etan Cohen0849ded2016-10-26 11:22:06 -0700602 WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper,
Etan Cohen3de35a52016-12-19 15:54:51 -0800603 boolean isPublish, DiscoverySessionCallback originalCallback,
Etan Cohen0849ded2016-10-26 11:22:06 -0700604 int clientId) {
605 mAwareManager = new WeakReference<>(mgr);
Etan Cohen231859c2016-03-14 18:06:46 -0700606 mIsPublish = isPublish;
607 mOriginalCallback = originalCallback;
Etan Cohenbd4bf352016-09-15 12:15:10 -0700608 mClientId = clientId;
Etan Cohen231859c2016-03-14 18:06:46 -0700609
Etan Cohen38553702016-09-14 14:41:56 -0700610 if (VDBG) {
Etan Cohen0849ded2016-10-26 11:22:06 -0700611 Log.v(TAG, "WifiAwareDiscoverySessionCallbackProxy ctor: isPublish=" + isPublish);
Etan Cohen38553702016-09-14 14:41:56 -0700612 }
Etan Cohen231859c2016-03-14 18:06:46 -0700613
614 mHandler = new Handler(looper) {
615 @Override
616 public void handleMessage(Message msg) {
617 if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
Etan Cohen51181fb2016-03-18 08:43:38 -0700618
Etan Cohen0849ded2016-10-26 11:22:06 -0700619 if (mAwareManager.get() == null) {
620 Log.w(TAG, "WifiAwareDiscoverySessionCallbackProxy: handleMessage post GC");
Etan Cohen51181fb2016-03-18 08:43:38 -0700621 return;
622 }
623
Etan Cohen231859c2016-03-14 18:06:46 -0700624 switch (msg.what) {
625 case CALLBACK_SESSION_STARTED:
626 onProxySessionStarted(msg.arg1);
627 break;
Etan Cohen51181fb2016-03-18 08:43:38 -0700628 case CALLBACK_SESSION_CONFIG_SUCCESS:
Etan Cohenb68ed282016-09-20 09:23:33 -0700629 mOriginalCallback.onSessionConfigUpdated();
Etan Cohen51181fb2016-03-18 08:43:38 -0700630 break;
Etan Cohen231859c2016-03-14 18:06:46 -0700631 case CALLBACK_SESSION_CONFIG_FAIL:
Etan Cohen5542ccc2016-09-21 14:37:02 -0700632 mOriginalCallback.onSessionConfigFailed();
Etan Cohen51181fb2016-03-18 08:43:38 -0700633 if (mSession == null) {
634 /*
635 * creation failed (as opposed to update
636 * failing)
637 */
Etan Cohen0849ded2016-10-26 11:22:06 -0700638 mAwareManager.clear();
Etan Cohen51181fb2016-03-18 08:43:38 -0700639 }
Etan Cohen231859c2016-03-14 18:06:46 -0700640 break;
641 case CALLBACK_SESSION_TERMINATED:
642 onProxySessionTerminated(msg.arg1);
643 break;
Etan Cohen88aa12b2017-11-08 08:41:39 -0800644 case CALLBACK_MATCH:
645 case CALLBACK_MATCH_WITH_DISTANCE:
646 {
Etan Cohen1857b982016-11-23 11:11:23 -0800647 List<byte[]> matchFilter = null;
648 byte[] arg = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2);
649 try {
650 matchFilter = new TlvBufferUtils.TlvIterable(0, 1, arg).toList();
651 } catch (BufferOverflowException e) {
652 matchFilter = null;
653 Log.e(TAG, "onServiceDiscovered: invalid match filter byte array '"
654 + new String(HexEncoding.encode(arg))
655 + "' - cannot be parsed: e=" + e);
656 }
Etan Cohen88aa12b2017-11-08 08:41:39 -0800657 if (msg.what == CALLBACK_MATCH) {
658 mOriginalCallback.onServiceDiscovered(new PeerHandle(msg.arg1),
659 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
660 matchFilter);
661 } else {
662 mOriginalCallback.onServiceDiscoveredWithinRange(
663 new PeerHandle(msg.arg1),
664 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
665 matchFilter, msg.arg2);
666 }
Etan Cohen231859c2016-03-14 18:06:46 -0700667 break;
Etan Cohen1857b982016-11-23 11:11:23 -0800668 }
Etan Cohen231859c2016-03-14 18:06:46 -0700669 case CALLBACK_MESSAGE_SEND_SUCCESS:
Etan Cohen6831f932016-11-16 13:40:55 -0800670 mOriginalCallback.onMessageSendSucceeded(msg.arg1);
Etan Cohen231859c2016-03-14 18:06:46 -0700671 break;
672 case CALLBACK_MESSAGE_SEND_FAIL:
Etan Cohen5542ccc2016-09-21 14:37:02 -0700673 mOriginalCallback.onMessageSendFailed(msg.arg1);
Etan Cohen231859c2016-03-14 18:06:46 -0700674 break;
675 case CALLBACK_MESSAGE_RECEIVED:
Etan Cohen6831f932016-11-16 13:40:55 -0800676 mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1),
Etan Cohen27c18cb2016-09-22 08:18:36 -0700677 (byte[]) msg.obj);
Etan Cohen231859c2016-03-14 18:06:46 -0700678 break;
679 }
680 }
681 };
682 }
683
684 @Override
685 public void onSessionStarted(int sessionId) {
686 if (VDBG) Log.v(TAG, "onSessionStarted: sessionId=" + sessionId);
687
688 Message msg = mHandler.obtainMessage(CALLBACK_SESSION_STARTED);
689 msg.arg1 = sessionId;
690 mHandler.sendMessage(msg);
691 }
692
693 @Override
Etan Cohen51181fb2016-03-18 08:43:38 -0700694 public void onSessionConfigSuccess() {
695 if (VDBG) Log.v(TAG, "onSessionConfigSuccess");
696
697 Message msg = mHandler.obtainMessage(CALLBACK_SESSION_CONFIG_SUCCESS);
698 mHandler.sendMessage(msg);
699 }
700
701 @Override
Etan Cohen231859c2016-03-14 18:06:46 -0700702 public void onSessionConfigFail(int reason) {
703 if (VDBG) Log.v(TAG, "onSessionConfigFail: reason=" + reason);
704
705 Message msg = mHandler.obtainMessage(CALLBACK_SESSION_CONFIG_FAIL);
706 msg.arg1 = reason;
707 mHandler.sendMessage(msg);
708 }
709
710 @Override
711 public void onSessionTerminated(int reason) {
712 if (VDBG) Log.v(TAG, "onSessionTerminated: reason=" + reason);
713
714 Message msg = mHandler.obtainMessage(CALLBACK_SESSION_TERMINATED);
715 msg.arg1 = reason;
716 mHandler.sendMessage(msg);
717 }
718
Etan Cohen88aa12b2017-11-08 08:41:39 -0800719 private void onMatchCommon(int messageType, int peerId, byte[] serviceSpecificInfo,
720 byte[] matchFilter, int distanceMm) {
Etan Cohen231859c2016-03-14 18:06:46 -0700721 Bundle data = new Bundle();
Etan Cohen231859c2016-03-14 18:06:46 -0700722 data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, serviceSpecificInfo);
723 data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2, matchFilter);
724
Etan Cohen88aa12b2017-11-08 08:41:39 -0800725 Message msg = mHandler.obtainMessage(messageType);
Etan Cohenee58a682016-07-15 15:28:39 -0700726 msg.arg1 = peerId;
Etan Cohen88aa12b2017-11-08 08:41:39 -0800727 msg.arg2 = distanceMm;
Etan Cohen231859c2016-03-14 18:06:46 -0700728 msg.setData(data);
729 mHandler.sendMessage(msg);
730 }
731
732 @Override
Etan Cohen88aa12b2017-11-08 08:41:39 -0800733 public void onMatch(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter) {
734 if (VDBG) Log.v(TAG, "onMatch: peerId=" + peerId);
735
736 onMatchCommon(CALLBACK_MATCH, peerId, serviceSpecificInfo, matchFilter, 0);
737 }
738
739 @Override
740 public void onMatchWithDistance(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter,
741 int distanceMm) {
742 if (VDBG) {
743 Log.v(TAG, "onMatchWithDistance: peerId=" + peerId + ", distanceMm=" + distanceMm);
744 }
745
746 onMatchCommon(CALLBACK_MATCH_WITH_DISTANCE, peerId, serviceSpecificInfo, matchFilter,
747 distanceMm);
748 }
749
750 @Override
Etan Cohen231859c2016-03-14 18:06:46 -0700751 public void onMessageSendSuccess(int messageId) {
752 if (VDBG) Log.v(TAG, "onMessageSendSuccess");
753
754 Message msg = mHandler.obtainMessage(CALLBACK_MESSAGE_SEND_SUCCESS);
755 msg.arg1 = messageId;
756 mHandler.sendMessage(msg);
757 }
758
759 @Override
760 public void onMessageSendFail(int messageId, int reason) {
761 if (VDBG) Log.v(TAG, "onMessageSendFail: reason=" + reason);
762
763 Message msg = mHandler.obtainMessage(CALLBACK_MESSAGE_SEND_FAIL);
764 msg.arg1 = messageId;
765 msg.arg2 = reason;
766 mHandler.sendMessage(msg);
767 }
768
769 @Override
Etan Cohenee58a682016-07-15 15:28:39 -0700770 public void onMessageReceived(int peerId, byte[] message) {
Etan Cohen231859c2016-03-14 18:06:46 -0700771 if (VDBG) {
Etan Cohen1857b982016-11-23 11:11:23 -0800772 Log.v(TAG, "onMessageReceived: peerId=" + peerId);
Etan Cohen231859c2016-03-14 18:06:46 -0700773 }
774
Etan Cohen231859c2016-03-14 18:06:46 -0700775 Message msg = mHandler.obtainMessage(CALLBACK_MESSAGE_RECEIVED);
Etan Cohenee58a682016-07-15 15:28:39 -0700776 msg.arg1 = peerId;
777 msg.obj = message;
Etan Cohen231859c2016-03-14 18:06:46 -0700778 mHandler.sendMessage(msg);
779 }
780
781 /*
782 * Proxied methods
783 */
784 public void onProxySessionStarted(int sessionId) {
785 if (VDBG) Log.v(TAG, "Proxy: onSessionStarted: sessionId=" + sessionId);
786 if (mSession != null) {
787 Log.e(TAG,
788 "onSessionStarted: sessionId=" + sessionId + ": session already created!?");
789 throw new IllegalStateException(
790 "onSessionStarted: sessionId=" + sessionId + ": session already created!?");
791 }
Etan Cohen51181fb2016-03-18 08:43:38 -0700792
Etan Cohen0849ded2016-10-26 11:22:06 -0700793 WifiAwareManager mgr = mAwareManager.get();
Etan Cohen51181fb2016-03-18 08:43:38 -0700794 if (mgr == null) {
795 Log.w(TAG, "onProxySessionStarted: mgr GC'd");
796 return;
797 }
798
Etan Cohen231859c2016-03-14 18:06:46 -0700799 if (mIsPublish) {
Etan Cohen3de35a52016-12-19 15:54:51 -0800800 PublishDiscoverySession session = new PublishDiscoverySession(mgr,
Etan Cohenbd4bf352016-09-15 12:15:10 -0700801 mClientId, sessionId);
Etan Cohen231859c2016-03-14 18:06:46 -0700802 mSession = session;
803 mOriginalCallback.onPublishStarted(session);
804 } else {
Etan Cohen3de35a52016-12-19 15:54:51 -0800805 SubscribeDiscoverySession
806 session = new SubscribeDiscoverySession(mgr, mClientId, sessionId);
Etan Cohen231859c2016-03-14 18:06:46 -0700807 mSession = session;
808 mOriginalCallback.onSubscribeStarted(session);
809 }
810 }
811
Etan Cohen231859c2016-03-14 18:06:46 -0700812 public void onProxySessionTerminated(int reason) {
813 if (VDBG) Log.v(TAG, "Proxy: onSessionTerminated: reason=" + reason);
Etan Cohen231859c2016-03-14 18:06:46 -0700814 if (mSession != null) {
Etan Cohen51181fb2016-03-18 08:43:38 -0700815 mSession.setTerminated();
816 mSession = null;
Etan Cohen231859c2016-03-14 18:06:46 -0700817 } else {
818 Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?");
819 }
Etan Cohen0849ded2016-10-26 11:22:06 -0700820 mAwareManager.clear();
Etan Cohenb84ad802016-12-24 12:44:59 -0800821 mOriginalCallback.onSessionTerminated();
Etan Cohen231859c2016-03-14 18:06:46 -0700822 }
823 }
Etan Cohen20d329b2015-09-29 13:49:02 -0700824}