Merge "NAN: baseline NAN manager for discovery." into mm-wireless-dev
This commit is contained in:
@@ -410,6 +410,9 @@ LOCAL_SRC_FILES += \
|
||||
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
|
||||
wifi/java/android/net/wifi/IWifiManager.aidl \
|
||||
wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
|
||||
wifi/java/android/net/wifi/nan/IWifiNanEventListener.aidl \
|
||||
wifi/java/android/net/wifi/nan/IWifiNanManager.aidl \
|
||||
wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl \
|
||||
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
|
||||
wifi/java/android/net/wifi/IWifiScanner.aidl \
|
||||
wifi/java/android/net/wifi/IRttManager.aidl \
|
||||
@@ -476,6 +479,11 @@ aidl_files := \
|
||||
frameworks/base/media/java/android/media/tv/TvTrackInfo.aidl \
|
||||
frameworks/base/media/java/android/media/browse/MediaBrowser.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/ScanSettings.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/nan/ConfigRequest.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/nan/PublishData.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/nan/SubscribeData.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/nan/PublishSettings.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/nan/SubscribeSettings.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl \
|
||||
frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl \
|
||||
|
||||
@@ -78,6 +78,8 @@ import android.net.wifi.IWifiScanner;
|
||||
import android.net.wifi.RttManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.net.wifi.WifiScanner;
|
||||
import android.net.wifi.nan.IWifiNanManager;
|
||||
import android.net.wifi.nan.WifiNanManager;
|
||||
import android.net.wifi.p2p.IWifiP2pManager;
|
||||
import android.net.wifi.p2p.WifiP2pManager;
|
||||
import android.net.wifi.passpoint.IWifiPasspointManager;
|
||||
@@ -499,6 +501,18 @@ final class SystemServiceRegistry {
|
||||
return new WifiP2pManager(service);
|
||||
}});
|
||||
|
||||
registerService(Context.WIFI_NAN_SERVICE, WifiNanManager.class,
|
||||
new StaticServiceFetcher<WifiNanManager>() {
|
||||
@Override
|
||||
public WifiNanManager createService() {
|
||||
IBinder b = ServiceManager.getService(Context.WIFI_NAN_SERVICE);
|
||||
IWifiNanManager service = IWifiNanManager.Stub.asInterface(b);
|
||||
if (service == null) {
|
||||
return null;
|
||||
}
|
||||
return new WifiNanManager(service);
|
||||
}});
|
||||
|
||||
registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class,
|
||||
new CachedServiceFetcher<WifiScanner>() {
|
||||
@Override
|
||||
|
||||
@@ -2460,6 +2460,7 @@ public abstract class Context {
|
||||
NETWORK_STATS_SERVICE,
|
||||
//@hide: NETWORK_POLICY_SERVICE,
|
||||
WIFI_SERVICE,
|
||||
WIFI_NAN_SERVICE,
|
||||
WIFI_PASSPOINT_SERVICE,
|
||||
WIFI_P2P_SERVICE,
|
||||
WIFI_SCANNING_SERVICE,
|
||||
@@ -2921,6 +2922,17 @@ public abstract class Context {
|
||||
*/
|
||||
public static final String WIFI_P2P_SERVICE = "wifip2p";
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a
|
||||
* {@link android.net.wifi.nan.WifiNanManager} for handling management of
|
||||
* Wi-Fi NAN discovery and connections.
|
||||
*
|
||||
* @see #getSystemService
|
||||
* @see android.net.wifi.nan.WifiNanManager
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public static final String WIFI_NAN_SERVICE = "wifinan";
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a {@link
|
||||
* android.net.wifi.WifiScanner} for scanning the wifi universe
|
||||
|
||||
@@ -1641,6 +1641,16 @@ public abstract class PackageManager {
|
||||
@SdkConstant(SdkConstantType.FEATURE)
|
||||
public static final String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
|
||||
|
||||
/**
|
||||
* Feature for {@link #getSystemAvailableFeatures} and
|
||||
* {@link #hasSystemFeature}: The device supports Wi-Fi Aware (NAN)
|
||||
* networking.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.FEATURE)
|
||||
public static final String FEATURE_WIFI_NAN = "android.hardware.wifi.nan";
|
||||
|
||||
/**
|
||||
* Feature for {@link #getSystemAvailableFeatures} and
|
||||
* {@link #hasSystemFeature}: This is a device dedicated to showing UI
|
||||
|
||||
@@ -130,6 +130,8 @@ public final class SystemServer {
|
||||
"com.android.server.midi.MidiService$Lifecycle";
|
||||
private static final String WIFI_SERVICE_CLASS =
|
||||
"com.android.server.wifi.WifiService";
|
||||
private static final String WIFI_NAN_SERVICE_CLASS =
|
||||
"com.android.server.wifi.nan.WifiNanService";
|
||||
private static final String WIFI_P2P_SERVICE_CLASS =
|
||||
"com.android.server.wifi.p2p.WifiP2pService";
|
||||
private static final String ETHERNET_SERVICE_CLASS =
|
||||
@@ -727,6 +729,11 @@ public final class SystemServer {
|
||||
}
|
||||
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
|
||||
|
||||
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_NAN)) {
|
||||
mSystemServiceManager.startService(WIFI_NAN_SERVICE_CLASS);
|
||||
} else {
|
||||
Slog.i(TAG, "No Wi-Fi NAN Service (NAN support Not Present)");
|
||||
}
|
||||
mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
|
||||
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
|
||||
mSystemServiceManager.startService(
|
||||
|
||||
@@ -999,7 +999,7 @@ public class WifiManager {
|
||||
|
||||
/**
|
||||
* @return true if this adapter supports Neighbour Awareness Network APIs
|
||||
* @hide
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public boolean isNanSupported() {
|
||||
return isFeatureSupported(WIFI_FEATURE_NAN);
|
||||
|
||||
19
wifi/java/android/net/wifi/nan/ConfigRequest.aidl
Normal file
19
wifi/java/android/net/wifi/nan/ConfigRequest.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
parcelable ConfigRequest;
|
||||
262
wifi/java/android/net/wifi/nan/ConfigRequest.java
Normal file
262
wifi/java/android/net/wifi/nan/ConfigRequest.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Defines a request object to configure a Wi-Fi NAN network. Built using
|
||||
* {@link ConfigRequest.Builder}. Configuration is requested using
|
||||
* {@link WifiNanManager#requestConfig(ConfigRequest)}. Note that the actual
|
||||
* achieved configuration may be different from the requested configuration -
|
||||
* since multiple applications may request different configurations.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class ConfigRequest implements Parcelable {
|
||||
/**
|
||||
* Lower range of possible cluster ID.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int CLUSTER_ID_MIN = 0;
|
||||
|
||||
/**
|
||||
* Upper range of possible cluster ID.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int CLUSTER_ID_MAX = 0xFFFF;
|
||||
|
||||
/**
|
||||
* Indicates whether 5G band support is requested.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final boolean mSupport5gBand;
|
||||
|
||||
/**
|
||||
* Specifies the desired master preference.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final int mMasterPreference;
|
||||
|
||||
/**
|
||||
* Specifies the desired lower range of the cluster ID. Must be lower then
|
||||
* {@link ConfigRequest#mClusterHigh}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final int mClusterLow;
|
||||
|
||||
/**
|
||||
* Specifies the desired higher range of the cluster ID. Must be higher then
|
||||
* {@link ConfigRequest#mClusterLow}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final int mClusterHigh;
|
||||
|
||||
private ConfigRequest(boolean support5gBand, int masterPreference, int clusterLow,
|
||||
int clusterHigh) {
|
||||
mSupport5gBand = support5gBand;
|
||||
mMasterPreference = masterPreference;
|
||||
mClusterLow = clusterLow;
|
||||
mClusterHigh = clusterHigh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfigRequest [mSupport5gBand=" + mSupport5gBand + ", mMasterPreference="
|
||||
+ mMasterPreference + ", mClusterLow=" + mClusterLow + ", mClusterHigh="
|
||||
+ mClusterHigh + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mSupport5gBand ? 1 : 0);
|
||||
dest.writeInt(mMasterPreference);
|
||||
dest.writeInt(mClusterLow);
|
||||
dest.writeInt(mClusterHigh);
|
||||
}
|
||||
|
||||
public static final Creator<ConfigRequest> CREATOR = new Creator<ConfigRequest>() {
|
||||
@Override
|
||||
public ConfigRequest[] newArray(int size) {
|
||||
return new ConfigRequest[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigRequest createFromParcel(Parcel in) {
|
||||
boolean support5gBand = in.readInt() != 0;
|
||||
int masterPreference = in.readInt();
|
||||
int clusterLow = in.readInt();
|
||||
int clusterHigh = in.readInt();
|
||||
return new ConfigRequest(support5gBand, masterPreference, clusterLow, clusterHigh);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof ConfigRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConfigRequest lhs = (ConfigRequest) o;
|
||||
|
||||
return mSupport5gBand == lhs.mSupport5gBand && mMasterPreference == lhs.mMasterPreference
|
||||
&& mClusterLow == lhs.mClusterLow && mClusterHigh == lhs.mClusterHigh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + (mSupport5gBand ? 1 : 0);
|
||||
result = 31 * result + mMasterPreference;
|
||||
result = 31 * result + mClusterLow;
|
||||
result = 31 * result + mClusterHigh;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder used to build {@link ConfigRequest} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private boolean mSupport5gBand;
|
||||
private int mMasterPreference;
|
||||
private int mClusterLow;
|
||||
private int mClusterHigh;
|
||||
|
||||
/**
|
||||
* Default constructor for the Builder.
|
||||
*/
|
||||
public Builder() {
|
||||
mSupport5gBand = false;
|
||||
mMasterPreference = 0;
|
||||
mClusterLow = 0;
|
||||
mClusterHigh = CLUSTER_ID_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether 5G band support is required in this request.
|
||||
*
|
||||
* @param support5gBand Support for 5G band is required.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setSupport5gBand(boolean support5gBand) {
|
||||
mSupport5gBand = support5gBand;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the Master Preference requested. The permitted range is 0 to
|
||||
* 255 with 1 and 255 excluded (reserved).
|
||||
*
|
||||
* @param masterPreference The requested master preference
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setMasterPreference(int masterPreference) {
|
||||
if (masterPreference < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Master Preference specification must be non-negative");
|
||||
}
|
||||
if (masterPreference == 1 || masterPreference == 255 || masterPreference > 255) {
|
||||
throw new IllegalArgumentException("Master Preference specification must not "
|
||||
+ "exceed 255 or use 1 or 255 (reserved values)");
|
||||
}
|
||||
|
||||
mMasterPreference = masterPreference;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Cluster ID is generated randomly for new NAN networks. Specify
|
||||
* the lower range of the cluster ID. The upper range is specified using
|
||||
* the {@link ConfigRequest.Builder#setClusterHigh(int)}. The permitted
|
||||
* range is 0 to the value specified by
|
||||
* {@link ConfigRequest.Builder#setClusterHigh(int)}. Equality is
|
||||
* permitted which restricts the Cluster ID to the specified value.
|
||||
*
|
||||
* @param clusterLow The lower range of the generated cluster ID.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setClusterLow(..).setClusterHigh(..)}.
|
||||
*/
|
||||
public Builder setClusterLow(int clusterLow) {
|
||||
if (clusterLow < CLUSTER_ID_MIN) {
|
||||
throw new IllegalArgumentException("Cluster specification must be non-negative");
|
||||
}
|
||||
if (clusterLow > CLUSTER_ID_MAX) {
|
||||
throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
|
||||
}
|
||||
|
||||
mClusterLow = clusterLow;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Cluster ID is generated randomly for new NAN networks. Specify
|
||||
* the lower upper of the cluster ID. The lower range is specified using
|
||||
* the {@link ConfigRequest.Builder#setClusterLow(int)}. The permitted
|
||||
* range is the value specified by
|
||||
* {@link ConfigRequest.Builder#setClusterLow(int)} to 0xFFFF. Equality
|
||||
* is permitted which restricts the Cluster ID to the specified value.
|
||||
*
|
||||
* @param clusterHigh The upper range of the generated cluster ID.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setClusterLow(..).setClusterHigh(..)}.
|
||||
*/
|
||||
public Builder setClusterHigh(int clusterHigh) {
|
||||
if (clusterHigh < CLUSTER_ID_MIN) {
|
||||
throw new IllegalArgumentException("Cluster specification must be non-negative");
|
||||
}
|
||||
if (clusterHigh > CLUSTER_ID_MAX) {
|
||||
throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
|
||||
}
|
||||
|
||||
mClusterHigh = clusterHigh;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link ConfigRequest} given the current requests made on the
|
||||
* builder.
|
||||
*/
|
||||
public ConfigRequest build() {
|
||||
if (mClusterLow > mClusterHigh) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid argument combination - must have Cluster Low <= Cluster High");
|
||||
}
|
||||
|
||||
return new ConfigRequest(mSupport5gBand, mMasterPreference, mClusterLow, mClusterHigh);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
wifi/java/android/net/wifi/nan/IWifiNanEventListener.aidl
Normal file
32
wifi/java/android/net/wifi/nan/IWifiNanEventListener.aidl
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2016, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.net.wifi.nan.ConfigRequest;
|
||||
|
||||
/**
|
||||
* Callback interface that WifiNanManager implements
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface IWifiNanEventListener
|
||||
{
|
||||
void onConfigCompleted(in ConfigRequest completedConfig);
|
||||
void onConfigFailed(int reason);
|
||||
void onNanDown(int reason);
|
||||
void onIdentityChanged();
|
||||
}
|
||||
49
wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
Normal file
49
wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2016, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
|
||||
import android.net.wifi.nan.ConfigRequest;
|
||||
import android.net.wifi.nan.IWifiNanEventListener;
|
||||
import android.net.wifi.nan.IWifiNanSessionListener;
|
||||
import android.net.wifi.nan.PublishData;
|
||||
import android.net.wifi.nan.PublishSettings;
|
||||
import android.net.wifi.nan.SubscribeData;
|
||||
import android.net.wifi.nan.SubscribeSettings;
|
||||
|
||||
/**
|
||||
* Interface that WifiNanService implements
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IWifiNanManager
|
||||
{
|
||||
// client API
|
||||
void connect(in IBinder binder, in IWifiNanEventListener listener, int events);
|
||||
void disconnect(in IBinder binder);
|
||||
void requestConfig(in ConfigRequest configRequest);
|
||||
|
||||
// session API
|
||||
int createSession(in IWifiNanSessionListener listener, int events);
|
||||
void publish(int sessionId, in PublishData publishData, in PublishSettings publishSettings);
|
||||
void subscribe(int sessionId, in SubscribeData subscribeData,
|
||||
in SubscribeSettings subscribeSettings);
|
||||
void sendMessage(int sessionId, int peerId, in byte[] message, int messageLength);
|
||||
void stopSession(int sessionId);
|
||||
void destroySession(int sessionId);
|
||||
}
|
||||
38
wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
Normal file
38
wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2016, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
/**
|
||||
* Callback interface that WifiNanManager implements
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface IWifiNanSessionListener
|
||||
{
|
||||
void onPublishFail(int reason);
|
||||
void onPublishTerminated(int reason);
|
||||
|
||||
void onSubscribeFail(int reason);
|
||||
void onSubscribeTerminated(int reason);
|
||||
|
||||
void onMatch(int peerId, in byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength, in byte[] matchFilter, int matchFilterLength);
|
||||
|
||||
void onMessageSendSuccess();
|
||||
void onMessageSendFail(int reason);
|
||||
void onMessageReceived(int peerId, in byte[] message, int messageLength);
|
||||
}
|
||||
19
wifi/java/android/net/wifi/nan/PublishData.aidl
Normal file
19
wifi/java/android/net/wifi/nan/PublishData.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
parcelable PublishData;
|
||||
343
wifi/java/android/net/wifi/nan/PublishData.java
Normal file
343
wifi/java/android/net/wifi/nan/PublishData.java
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Defines the data for a NAN publish session. Built using
|
||||
* {@link PublishData.Builder}. Publish is done using
|
||||
* {@link WifiNanManager#publish(PublishData, PublishSettings, WifiNanSessionListener, int)}
|
||||
* or {@link WifiNanPublishSession#publish(PublishData, PublishSettings)}.
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class PublishData implements Parcelable {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final String mServiceName;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mServiceSpecificInfoLength;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final byte[] mServiceSpecificInfo;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mTxFilterLength;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final byte[] mTxFilter;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mRxFilterLength;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final byte[] mRxFilter;
|
||||
|
||||
private PublishData(String serviceName, byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength, byte[] txFilter, int txFilterLength, byte[] rxFilter,
|
||||
int rxFilterLength) {
|
||||
mServiceName = serviceName;
|
||||
mServiceSpecificInfoLength = serviceSpecificInfoLength;
|
||||
mServiceSpecificInfo = serviceSpecificInfo;
|
||||
mTxFilterLength = txFilterLength;
|
||||
mTxFilter = txFilter;
|
||||
mRxFilterLength = rxFilterLength;
|
||||
mRxFilter = rxFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PublishData [mServiceName='" + mServiceName + "', mServiceSpecificInfo='"
|
||||
+ (new String(mServiceSpecificInfo, 0, mServiceSpecificInfoLength))
|
||||
+ "', mTxFilter="
|
||||
+ (new TlvBufferUtils.TlvIterable(0, 1, mTxFilter, mTxFilterLength)).toString()
|
||||
+ ", mRxFilter="
|
||||
+ (new TlvBufferUtils.TlvIterable(0, 1, mRxFilter, mRxFilterLength)).toString()
|
||||
+ "']";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mServiceName);
|
||||
dest.writeInt(mServiceSpecificInfoLength);
|
||||
if (mServiceSpecificInfoLength != 0) {
|
||||
dest.writeByteArray(mServiceSpecificInfo, 0, mServiceSpecificInfoLength);
|
||||
}
|
||||
dest.writeInt(mTxFilterLength);
|
||||
if (mTxFilterLength != 0) {
|
||||
dest.writeByteArray(mTxFilter, 0, mTxFilterLength);
|
||||
}
|
||||
dest.writeInt(mRxFilterLength);
|
||||
if (mRxFilterLength != 0) {
|
||||
dest.writeByteArray(mRxFilter, 0, mRxFilterLength);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Creator<PublishData> CREATOR = new Creator<PublishData>() {
|
||||
@Override
|
||||
public PublishData[] newArray(int size) {
|
||||
return new PublishData[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublishData createFromParcel(Parcel in) {
|
||||
String serviceName = in.readString();
|
||||
int ssiLength = in.readInt();
|
||||
byte[] ssi = new byte[ssiLength];
|
||||
if (ssiLength != 0) {
|
||||
in.readByteArray(ssi);
|
||||
}
|
||||
int txFilterLength = in.readInt();
|
||||
byte[] txFilter = new byte[txFilterLength];
|
||||
if (txFilterLength != 0) {
|
||||
in.readByteArray(txFilter);
|
||||
}
|
||||
int rxFilterLength = in.readInt();
|
||||
byte[] rxFilter = new byte[rxFilterLength];
|
||||
if (rxFilterLength != 0) {
|
||||
in.readByteArray(rxFilter);
|
||||
}
|
||||
|
||||
return new PublishData(serviceName, ssi, ssiLength, txFilter, txFilterLength, rxFilter,
|
||||
rxFilterLength);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof PublishData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PublishData lhs = (PublishData) o;
|
||||
|
||||
if (!mServiceName.equals(lhs.mServiceName)
|
||||
|| mServiceSpecificInfoLength != lhs.mServiceSpecificInfoLength
|
||||
|| mTxFilterLength != lhs.mTxFilterLength
|
||||
|| mRxFilterLength != lhs.mRxFilterLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mServiceSpecificInfo != null && lhs.mServiceSpecificInfo != null) {
|
||||
for (int i = 0; i < mServiceSpecificInfoLength; ++i) {
|
||||
if (mServiceSpecificInfo[i] != lhs.mServiceSpecificInfo[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mServiceSpecificInfoLength != 0) {
|
||||
return false; // invalid != invalid
|
||||
}
|
||||
|
||||
if (mTxFilter != null && lhs.mTxFilter != null) {
|
||||
for (int i = 0; i < mTxFilterLength; ++i) {
|
||||
if (mTxFilter[i] != lhs.mTxFilter[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mTxFilterLength != 0) {
|
||||
return false; // invalid != invalid
|
||||
}
|
||||
|
||||
if (mRxFilter != null && lhs.mRxFilter != null) {
|
||||
for (int i = 0; i < mRxFilterLength; ++i) {
|
||||
if (mRxFilter[i] != lhs.mRxFilter[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mRxFilterLength != 0) {
|
||||
return false; // invalid != invalid
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + mServiceName.hashCode();
|
||||
result = 31 * result + mServiceSpecificInfoLength;
|
||||
result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
|
||||
result = 31 * result + mTxFilterLength;
|
||||
result = 31 * result + Arrays.hashCode(mTxFilter);
|
||||
result = 31 * result + mRxFilterLength;
|
||||
result = 31 * result + Arrays.hashCode(mRxFilter);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder used to build {@link PublishData} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private String mServiceName;
|
||||
private int mServiceSpecificInfoLength;
|
||||
private byte[] mServiceSpecificInfo = new byte[0];
|
||||
private int mTxFilterLength;
|
||||
private byte[] mTxFilter = new byte[0];
|
||||
private int mRxFilterLength;
|
||||
private byte[] mRxFilter = new byte[0];
|
||||
|
||||
/**
|
||||
* Specify the service name of the publish session. The actual on-air
|
||||
* value is a 6 byte hashed representation of this string.
|
||||
*
|
||||
* @param serviceName The service name for the publish session.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setServiceName(String serviceName) {
|
||||
mServiceName = serviceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify service specific information for the publish session. This is
|
||||
* a free-form byte array available to the application to send
|
||||
* additional information as part of the discovery operation - i.e. it
|
||||
* will not be used to determine whether a publish/subscribe match
|
||||
* occurs.
|
||||
*
|
||||
* @param serviceSpecificInfo A byte-array for the service-specific
|
||||
* information field.
|
||||
* @param serviceSpecificInfoLength The length of the byte-array to be
|
||||
* used.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setServiceSpecificInfo(byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength) {
|
||||
if (serviceSpecificInfoLength != 0 && (serviceSpecificInfo == null
|
||||
|| serviceSpecificInfo.length < serviceSpecificInfoLength)) {
|
||||
throw new IllegalArgumentException("Non-matching combination of "
|
||||
+ "serviceSpecificInfo and serviceSpecificInfoLength");
|
||||
}
|
||||
mServiceSpecificInfoLength = serviceSpecificInfoLength;
|
||||
mServiceSpecificInfo = serviceSpecificInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify service specific information for the publish session - same
|
||||
* as {@link PublishData.Builder#setServiceSpecificInfo(byte[], int)}
|
||||
* but obtaining the data from a String.
|
||||
*
|
||||
* @param serviceSpecificInfoStr The service specific information string
|
||||
* to be included (as a byte array) in the publish
|
||||
* information.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setServiceSpecificInfo(String serviceSpecificInfoStr) {
|
||||
mServiceSpecificInfoLength = serviceSpecificInfoStr.length();
|
||||
mServiceSpecificInfo = serviceSpecificInfoStr.getBytes();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The transmit filter for an active publish session
|
||||
* {@link PublishSettings.Builder#setPublishType(int)} and
|
||||
* {@link PublishSettings#PUBLISH_TYPE_UNSOLICITED}. Included in
|
||||
* transmitted publish packets and used by receivers (subscribers) to
|
||||
* determine whether they match - in addition to just relying on the
|
||||
* service name.
|
||||
* <p>
|
||||
* Format is an LV byte array - the {@link TlvBufferUtils} utility class
|
||||
* is available to form and parse.
|
||||
*
|
||||
* @param txFilter The byte-array containing the LV formatted transmit
|
||||
* filter.
|
||||
* @param txFilterLength The number of bytes in the transmit filter
|
||||
* argument.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setTxFilter(byte[] txFilter, int txFilterLength) {
|
||||
if (txFilterLength != 0 && (txFilter == null || txFilter.length < txFilterLength)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Non-matching combination of txFilter and txFilterLength");
|
||||
}
|
||||
mTxFilter = txFilter;
|
||||
mTxFilterLength = txFilterLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The transmit filter for a passive publish session
|
||||
* {@link PublishSettings.Builder#setPublishType(int)} and
|
||||
* {@link PublishSettings#PUBLISH_TYPE_SOLICITED}. Used by the publisher
|
||||
* to determine whether they match transmitted subscriber packets
|
||||
* (active subscribers) - in addition to just relying on the service
|
||||
* name.
|
||||
* <p>
|
||||
* Format is an LV byte array - the {@link TlvBufferUtils} utility class
|
||||
* is available to form and parse.
|
||||
*
|
||||
* @param rxFilter The byte-array containing the LV formatted receive
|
||||
* filter.
|
||||
* @param rxFilterLength The number of bytes in the receive filter
|
||||
* argument.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setRxFilter(byte[] rxFilter, int rxFilterLength) {
|
||||
if (rxFilterLength != 0 && (rxFilter == null || rxFilter.length < rxFilterLength)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Non-matching combination of rxFilter and rxFilterLength");
|
||||
}
|
||||
mRxFilter = rxFilter;
|
||||
mRxFilterLength = rxFilterLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link PublishData} given the current requests made on the
|
||||
* builder.
|
||||
*/
|
||||
public PublishData build() {
|
||||
return new PublishData(mServiceName, mServiceSpecificInfo, mServiceSpecificInfoLength,
|
||||
mTxFilter, mTxFilterLength, mRxFilter, mRxFilterLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
wifi/java/android/net/wifi/nan/PublishSettings.aidl
Normal file
19
wifi/java/android/net/wifi/nan/PublishSettings.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
parcelable PublishSettings;
|
||||
204
wifi/java/android/net/wifi/nan/PublishSettings.java
Normal file
204
wifi/java/android/net/wifi/nan/PublishSettings.java
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Defines the settings (configuration) for a NAN publish session. Built using
|
||||
* {@link PublishSettings.Builder}. Publish is done using
|
||||
* {@link WifiNanManager#publish(PublishData, PublishSettings, WifiNanSessionListener, int)}
|
||||
* or {@link WifiNanPublishSession#publish(PublishData, PublishSettings)}.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class PublishSettings implements Parcelable {
|
||||
|
||||
/**
|
||||
* Defines an unsolicited publish session - i.e. a publish session where
|
||||
* publish packets are transmitted over-the-air. Configuration is done using
|
||||
* {@link PublishSettings.Builder#setPublishType(int)}.
|
||||
*/
|
||||
public static final int PUBLISH_TYPE_UNSOLICITED = 0;
|
||||
|
||||
/**
|
||||
* Defines a solicited publish session - i.e. a publish session where
|
||||
* publish packets are not transmitted over-the-air and the device listens
|
||||
* and matches to transmitted subscribe packets. Configuration is done using
|
||||
* {@link PublishSettings.Builder#setPublishType(int)}.
|
||||
*/
|
||||
public static final int PUBLISH_TYPE_SOLICITED = 1;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mPublishType;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mPublishCount;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mTtlSec;
|
||||
|
||||
private PublishSettings(int publishType, int publichCount, int ttlSec) {
|
||||
mPublishType = publishType;
|
||||
mPublishCount = publichCount;
|
||||
mTtlSec = ttlSec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PublishSettings [mPublishType=" + mPublishType + ", mPublishCount=" + mPublishCount
|
||||
+ ", mTtlSec=" + mTtlSec + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mPublishType);
|
||||
dest.writeInt(mPublishCount);
|
||||
dest.writeInt(mTtlSec);
|
||||
}
|
||||
|
||||
public static final Creator<PublishSettings> CREATOR = new Creator<PublishSettings>() {
|
||||
@Override
|
||||
public PublishSettings[] newArray(int size) {
|
||||
return new PublishSettings[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublishSettings createFromParcel(Parcel in) {
|
||||
int publishType = in.readInt();
|
||||
int publishCount = in.readInt();
|
||||
int ttlSec = in.readInt();
|
||||
return new PublishSettings(publishType, publishCount, ttlSec);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof PublishSettings)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PublishSettings lhs = (PublishSettings) o;
|
||||
|
||||
return mPublishType == lhs.mPublishType && mPublishCount == lhs.mPublishCount
|
||||
&& mTtlSec == lhs.mTtlSec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + mPublishType;
|
||||
result = 31 * result + mPublishCount;
|
||||
result = 31 * result + mTtlSec;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder used to build {@link PublishSettings} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
int mPublishType;
|
||||
int mPublishCount;
|
||||
int mTtlSec;
|
||||
|
||||
/**
|
||||
* Sets the type of the publish session: solicited (aka active - publish
|
||||
* packets are transmitted over-the-air), or unsolicited (aka passive -
|
||||
* no publish packets are transmitted, a match is made against an active
|
||||
* subscribe session whose packets are transmitted over-the-air).
|
||||
*
|
||||
* @param publishType Publish session type: solicited (
|
||||
* {@link PublishSettings#PUBLISH_TYPE_SOLICITED}) or
|
||||
* unsolicited (
|
||||
* {@link PublishSettings#PUBLISH_TYPE_UNSOLICITED}).
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setPublishType(int publishType) {
|
||||
if (publishType < PUBLISH_TYPE_UNSOLICITED || publishType > PUBLISH_TYPE_SOLICITED) {
|
||||
throw new IllegalArgumentException("Invalid publishType - " + publishType);
|
||||
}
|
||||
mPublishType = publishType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of times a solicited (
|
||||
* {@link PublishSettings.Builder#setPublishType(int)}) publish session
|
||||
* will transmit a packet. When the count is reached an event will be
|
||||
* generated for {@link WifiNanSessionListener#onPublishTerminated(int)}
|
||||
* with reason={@link WifiNanSessionListener#TERMINATE_REASON_DONE}.
|
||||
*
|
||||
* @param publishCount Number of publish packets to transmit.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setPublishCount(int publishCount) {
|
||||
if (publishCount < 0) {
|
||||
throw new IllegalArgumentException("Invalid publishCount - must be non-negative");
|
||||
}
|
||||
mPublishCount = publishCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time interval (in seconds) a solicited (
|
||||
* {@link PublishSettings.Builder#setPublishCount(int)}) publish session
|
||||
* will be alive - i.e. transmitting a packet. When the TTL is reached
|
||||
* an event will be generated for
|
||||
* {@link WifiNanSessionListener#onPublishTerminated(int)} with reason=
|
||||
* {@link WifiNanSessionListener#TERMINATE_REASON_DONE}.
|
||||
*
|
||||
* @param ttlSec Lifetime of a publish session in seconds.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setTtlSec(int ttlSec) {
|
||||
if (ttlSec < 0) {
|
||||
throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
|
||||
}
|
||||
mTtlSec = ttlSec;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link PublishSettings} given the current requests made on the
|
||||
* builder.
|
||||
*/
|
||||
public PublishSettings build() {
|
||||
return new PublishSettings(mPublishType, mPublishCount, mTtlSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
wifi/java/android/net/wifi/nan/SubscribeData.aidl
Normal file
19
wifi/java/android/net/wifi/nan/SubscribeData.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
parcelable SubscribeData;
|
||||
329
wifi/java/android/net/wifi/nan/SubscribeData.java
Normal file
329
wifi/java/android/net/wifi/nan/SubscribeData.java
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Defines the data for a NAN subscribe session. Built using
|
||||
* {@link SubscribeData.Builder}. Subscribe is done using
|
||||
* {@link WifiNanManager#subscribe(SubscribeData, SubscribeSettings, WifiNanSessionListener, int)}
|
||||
* or
|
||||
* {@link WifiNanSubscribeSession#subscribe(SubscribeData, SubscribeSettings)}.
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class SubscribeData implements Parcelable {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final String mServiceName;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mServiceSpecificInfoLength;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final byte[] mServiceSpecificInfo;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mTxFilterLength;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final byte[] mTxFilter;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mRxFilterLength;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final byte[] mRxFilter;
|
||||
|
||||
private SubscribeData(String serviceName, byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength, byte[] txFilter, int txFilterLength, byte[] rxFilter,
|
||||
int rxFilterLength) {
|
||||
mServiceName = serviceName;
|
||||
mServiceSpecificInfoLength = serviceSpecificInfoLength;
|
||||
mServiceSpecificInfo = serviceSpecificInfo;
|
||||
mTxFilterLength = txFilterLength;
|
||||
mTxFilter = txFilter;
|
||||
mRxFilterLength = rxFilterLength;
|
||||
mRxFilter = rxFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SubscribeData [mServiceName='" + mServiceName + "', mServiceSpecificInfo='"
|
||||
+ (new String(mServiceSpecificInfo, 0, mServiceSpecificInfoLength))
|
||||
+ "', mTxFilter="
|
||||
+ (new TlvBufferUtils.TlvIterable(0, 1, mTxFilter, mTxFilterLength)).toString()
|
||||
+ ", mRxFilter="
|
||||
+ (new TlvBufferUtils.TlvIterable(0, 1, mRxFilter, mRxFilterLength)).toString()
|
||||
+ "']";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mServiceName);
|
||||
dest.writeInt(mServiceSpecificInfoLength);
|
||||
if (mServiceSpecificInfoLength != 0) {
|
||||
dest.writeByteArray(mServiceSpecificInfo, 0, mServiceSpecificInfoLength);
|
||||
}
|
||||
dest.writeInt(mTxFilterLength);
|
||||
if (mTxFilterLength != 0) {
|
||||
dest.writeByteArray(mTxFilter, 0, mTxFilterLength);
|
||||
}
|
||||
dest.writeInt(mRxFilterLength);
|
||||
if (mRxFilterLength != 0) {
|
||||
dest.writeByteArray(mRxFilter, 0, mRxFilterLength);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Creator<SubscribeData> CREATOR = new Creator<SubscribeData>() {
|
||||
@Override
|
||||
public SubscribeData[] newArray(int size) {
|
||||
return new SubscribeData[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubscribeData createFromParcel(Parcel in) {
|
||||
String serviceName = in.readString();
|
||||
int ssiLength = in.readInt();
|
||||
byte[] ssi = new byte[ssiLength];
|
||||
if (ssiLength != 0) {
|
||||
in.readByteArray(ssi);
|
||||
}
|
||||
int txFilterLength = in.readInt();
|
||||
byte[] txFilter = new byte[txFilterLength];
|
||||
if (txFilterLength != 0) {
|
||||
in.readByteArray(txFilter);
|
||||
}
|
||||
int rxFilterLength = in.readInt();
|
||||
byte[] rxFilter = new byte[rxFilterLength];
|
||||
if (rxFilterLength != 0) {
|
||||
in.readByteArray(rxFilter);
|
||||
}
|
||||
|
||||
return new SubscribeData(serviceName, ssi, ssiLength, txFilter, txFilterLength,
|
||||
rxFilter, rxFilterLength);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof SubscribeData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SubscribeData lhs = (SubscribeData) o;
|
||||
|
||||
if (!mServiceName.equals(lhs.mServiceName)
|
||||
|| mServiceSpecificInfoLength != lhs.mServiceSpecificInfoLength
|
||||
|| mTxFilterLength != lhs.mTxFilterLength
|
||||
|| mRxFilterLength != lhs.mRxFilterLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mServiceSpecificInfo != null && lhs.mServiceSpecificInfo != null) {
|
||||
for (int i = 0; i < mServiceSpecificInfoLength; ++i) {
|
||||
if (mServiceSpecificInfo[i] != lhs.mServiceSpecificInfo[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mServiceSpecificInfoLength != 0) {
|
||||
return false; // invalid != invalid
|
||||
}
|
||||
|
||||
if (mTxFilter != null && lhs.mTxFilter != null) {
|
||||
for (int i = 0; i < mTxFilterLength; ++i) {
|
||||
if (mTxFilter[i] != lhs.mTxFilter[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mTxFilterLength != 0) {
|
||||
return false; // invalid != invalid
|
||||
}
|
||||
|
||||
if (mRxFilter != null && lhs.mRxFilter != null) {
|
||||
for (int i = 0; i < mRxFilterLength; ++i) {
|
||||
if (mRxFilter[i] != lhs.mRxFilter[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mRxFilterLength != 0) {
|
||||
return false; // invalid != invalid
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + mServiceName.hashCode();
|
||||
result = 31 * result + mServiceSpecificInfoLength;
|
||||
result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
|
||||
result = 31 * result + mTxFilterLength;
|
||||
result = 31 * result + Arrays.hashCode(mTxFilter);
|
||||
result = 31 * result + mRxFilterLength;
|
||||
result = 31 * result + Arrays.hashCode(mRxFilter);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder used to build {@link SubscribeData} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private String mServiceName;
|
||||
private int mServiceSpecificInfoLength;
|
||||
private byte[] mServiceSpecificInfo = new byte[0];
|
||||
private int mTxFilterLength;
|
||||
private byte[] mTxFilter = new byte[0];
|
||||
private int mRxFilterLength;
|
||||
private byte[] mRxFilter = new byte[0];
|
||||
|
||||
/**
|
||||
* Specify the service name of the subscribe session. The actual on-air
|
||||
* value is a 6 byte hashed representation of this string.
|
||||
*
|
||||
* @param serviceName The service name for the subscribe session.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setServiceName(String serviceName) {
|
||||
mServiceName = serviceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify service specific information for the subscribe session. This
|
||||
* is a free-form byte array available to the application to send
|
||||
* additional information as part of the discovery operation - i.e. it
|
||||
* will not be used to determine whether a publish/subscribe match
|
||||
* occurs.
|
||||
*
|
||||
* @param serviceSpecificInfo A byte-array for the service-specific
|
||||
* information field.
|
||||
* @param serviceSpecificInfoLength The length of the byte-array to be
|
||||
* used.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setServiceSpecificInfo(byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength) {
|
||||
mServiceSpecificInfoLength = serviceSpecificInfoLength;
|
||||
mServiceSpecificInfo = serviceSpecificInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify service specific information for the subscribe session - same
|
||||
* as {@link SubscribeData.Builder#setServiceSpecificInfo(byte[], int)}
|
||||
* but obtaining the data from a String.
|
||||
*
|
||||
* @param serviceSpecificInfoStr The service specific information string
|
||||
* to be included (as a byte array) in the subscribe
|
||||
* information.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setServiceSpecificInfo(String serviceSpecificInfoStr) {
|
||||
mServiceSpecificInfoLength = serviceSpecificInfoStr.length();
|
||||
mServiceSpecificInfo = serviceSpecificInfoStr.getBytes();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The transmit filter for an active subscribe session
|
||||
* {@link SubscribeSettings.Builder#setSubscribeType(int)} and
|
||||
* {@link SubscribeSettings#SUBSCRIBE_TYPE_ACTIVE}. Included in
|
||||
* transmitted subscribe packets and used by receivers (passive
|
||||
* publishers) to determine whether they match - in addition to just
|
||||
* relying on the service name.
|
||||
* <p>
|
||||
* Format is an LV byte array - the {@link TlvBufferUtils} utility class
|
||||
* is available to form and parse.
|
||||
*
|
||||
* @param txFilter The byte-array containing the LV formatted transmit
|
||||
* filter.
|
||||
* @param txFilterLength The number of bytes in the transmit filter
|
||||
* argument.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setTxFilter(byte[] txFilter, int txFilterLength) {
|
||||
mTxFilter = txFilter;
|
||||
mTxFilterLength = txFilterLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The transmit filter for a passive subsribe session
|
||||
* {@link SubscribeSettings.Builder#setSubscribeType(int)} and
|
||||
* {@link SubscribeSettings#SUBSCRIBE_TYPE_PASSIVE}. Used by the
|
||||
* subscriber to determine whether they match transmitted publish
|
||||
* packets - in addition to just relying on the service name.
|
||||
* <p>
|
||||
* Format is an LV byte array - the {@link TlvBufferUtils} utility class
|
||||
* is available to form and parse.
|
||||
*
|
||||
* @param rxFilter The byte-array containing the LV formatted receive
|
||||
* filter.
|
||||
* @param rxFilterLength The number of bytes in the receive filter
|
||||
* argument.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setRxFilter(byte[] rxFilter, int rxFilterLength) {
|
||||
mRxFilter = rxFilter;
|
||||
mRxFilterLength = rxFilterLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link SubscribeData} given the current requests made on the
|
||||
* builder.
|
||||
*/
|
||||
public SubscribeData build() {
|
||||
return new SubscribeData(mServiceName, mServiceSpecificInfo, mServiceSpecificInfoLength,
|
||||
mTxFilter, mTxFilterLength, mRxFilter, mRxFilterLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
wifi/java/android/net/wifi/nan/SubscribeSettings.aidl
Normal file
19
wifi/java/android/net/wifi/nan/SubscribeSettings.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
parcelable SubscribeSettings;
|
||||
205
wifi/java/android/net/wifi/nan/SubscribeSettings.java
Normal file
205
wifi/java/android/net/wifi/nan/SubscribeSettings.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Defines the settings (configuration) for a NAN subscribe session. Built using
|
||||
* {@link SubscribeSettings.Builder}. Subscribe is done using
|
||||
* {@link WifiNanManager#subscribe(SubscribeData, SubscribeSettings, WifiNanSessionListener, int)}
|
||||
* or {@link WifiNanSubscribeSession#subscribe(SubscribeData, SubscribeSettings)}.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class SubscribeSettings implements Parcelable {
|
||||
|
||||
/**
|
||||
* Defines a passive subscribe session - i.e. a subscribe session where
|
||||
* subscribe packets are not transmitted over-the-air and the device listens
|
||||
* and matches to transmitted publish packets. Configuration is done using
|
||||
* {@link SubscribeSettings.Builder#setSubscribeType(int)}.
|
||||
*/
|
||||
public static final int SUBSCRIBE_TYPE_PASSIVE = 0;
|
||||
|
||||
/**
|
||||
* Defines an active subscribe session - i.e. a subscribe session where
|
||||
* subscribe packets are transmitted over-the-air. Configuration is done
|
||||
* using {@link SubscribeSettings.Builder#setSubscribeType(int)}.
|
||||
*/
|
||||
public static final int SUBSCRIBE_TYPE_ACTIVE = 1;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mSubscribeType;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mSubscribeCount;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final int mTtlSec;
|
||||
|
||||
private SubscribeSettings(int subscribeType, int publichCount, int ttlSec) {
|
||||
mSubscribeType = subscribeType;
|
||||
mSubscribeCount = publichCount;
|
||||
mTtlSec = ttlSec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SubscribeSettings [mSubscribeType=" + mSubscribeType + ", mSubscribeCount="
|
||||
+ mSubscribeCount + ", mTtlSec=" + mTtlSec + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mSubscribeType);
|
||||
dest.writeInt(mSubscribeCount);
|
||||
dest.writeInt(mTtlSec);
|
||||
}
|
||||
|
||||
public static final Creator<SubscribeSettings> CREATOR = new Creator<SubscribeSettings>() {
|
||||
@Override
|
||||
public SubscribeSettings[] newArray(int size) {
|
||||
return new SubscribeSettings[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubscribeSettings createFromParcel(Parcel in) {
|
||||
int subscribeType = in.readInt();
|
||||
int subscribeCount = in.readInt();
|
||||
int ttlSec = in.readInt();
|
||||
return new SubscribeSettings(subscribeType, subscribeCount, ttlSec);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof SubscribeSettings)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SubscribeSettings lhs = (SubscribeSettings) o;
|
||||
|
||||
return mSubscribeType == lhs.mSubscribeType && mSubscribeCount == lhs.mSubscribeCount
|
||||
&& mTtlSec == lhs.mTtlSec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + mSubscribeType;
|
||||
result = 31 * result + mSubscribeCount;
|
||||
result = 31 * result + mTtlSec;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder used to build {@link SubscribeSettings} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
int mSubscribeType;
|
||||
int mSubscribeCount;
|
||||
int mTtlSec;
|
||||
|
||||
/**
|
||||
* Sets the type of the subscribe session: active (subscribe packets are
|
||||
* transmitted over-the-air), or passive (no subscribe packets are
|
||||
* transmitted, a match is made against a solicited/active publish
|
||||
* session whose packets are transmitted over-the-air).
|
||||
*
|
||||
* @param subscribeType Subscribe session type: active (
|
||||
* {@link SubscribeSettings#SUBSCRIBE_TYPE_ACTIVE}) or
|
||||
* passive ( {@link SubscribeSettings#SUBSCRIBE_TYPE_PASSIVE}
|
||||
* ).
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setSubscribeType(int subscribeType) {
|
||||
if (subscribeType < SUBSCRIBE_TYPE_PASSIVE || subscribeType > SUBSCRIBE_TYPE_ACTIVE) {
|
||||
throw new IllegalArgumentException("Invalid subscribeType - " + subscribeType);
|
||||
}
|
||||
mSubscribeType = subscribeType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of times an active (
|
||||
* {@link SubscribeSettings.Builder#setSubscribeType(int)}) subscribe
|
||||
* session will transmit a packet. When the count is reached an event
|
||||
* will be generated for
|
||||
* {@link WifiNanSessionListener#onSubscribeTerminated(int)} with reason=
|
||||
* {@link WifiNanSessionListener#TERMINATE_REASON_DONE}.
|
||||
*
|
||||
* @param subscribeCount Number of subscribe packets to transmit.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setSubscribeCount(int subscribeCount) {
|
||||
if (subscribeCount < 0) {
|
||||
throw new IllegalArgumentException("Invalid subscribeCount - must be non-negative");
|
||||
}
|
||||
mSubscribeCount = subscribeCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time interval (in seconds) an active (
|
||||
* {@link SubscribeSettings.Builder#setSubscribeType(int)}) subscribe
|
||||
* session will be alive - i.e. transmitting a packet. When the TTL is
|
||||
* reached an event will be generated for
|
||||
* {@link WifiNanSessionListener#onSubscribeTerminated(int)} with reason=
|
||||
* {@link WifiNanSessionListener#TERMINATE_REASON_DONE}.
|
||||
*
|
||||
* @param ttlSec Lifetime of a subscribe session in seconds.
|
||||
* @return The builder to facilitate chaining
|
||||
* {@code builder.setXXX(..).setXXX(..)}.
|
||||
*/
|
||||
public Builder setTtlSec(int ttlSec) {
|
||||
if (ttlSec < 0) {
|
||||
throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
|
||||
}
|
||||
mTtlSec = ttlSec;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link SubscribeSettings} given the current requests made on
|
||||
* the builder.
|
||||
*/
|
||||
public SubscribeSettings build() {
|
||||
return new SubscribeSettings(mSubscribeType, mSubscribeCount, mTtlSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
490
wifi/java/android/net/wifi/nan/TlvBufferUtils.java
Normal file
490
wifi/java/android/net/wifi/nan/TlvBufferUtils.java
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import libcore.io.Memory;
|
||||
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Utility class to construct and parse byte arrays using the TLV format -
|
||||
* Type/Length/Value format. The utilities accept a configuration of the size of
|
||||
* the Type field and the Length field. A Type field size of 0 is allowed -
|
||||
* allowing usage for LV (no T) array formats.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class TlvBufferUtils {
|
||||
private TlvBufferUtils() {
|
||||
// no reason to ever create this class
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to construct byte arrays using the TLV format -
|
||||
* Type/Length/Value.
|
||||
* <p>
|
||||
* A constructor is created specifying the size of the Type (T) and Length
|
||||
* (L) fields. A specification of zero size T field is allowed - resulting
|
||||
* in LV type format.
|
||||
* <p>
|
||||
* The byte array is either provided (using
|
||||
* {@link TlvConstructor#wrap(byte[])}) or allocated (using
|
||||
* {@link TlvConstructor#allocate(int)}).
|
||||
* <p>
|
||||
* Values are added to the structure using the {@code TlvConstructor.put*()}
|
||||
* methods.
|
||||
* <p>
|
||||
* The final byte array is obtained using {@link TlvConstructor#getArray()}
|
||||
* and {@link TlvConstructor#getActualLength()} methods.
|
||||
*/
|
||||
public static class TlvConstructor {
|
||||
private int mTypeSize;
|
||||
private int mLengthSize;
|
||||
|
||||
private byte[] mArray;
|
||||
private int mArrayLength;
|
||||
private int mPosition;
|
||||
|
||||
/**
|
||||
* Define a TLV constructor with the specified size of the Type (T) and
|
||||
* Length (L) fields.
|
||||
*
|
||||
* @param typeSize Number of bytes used for the Type (T) field. Values
|
||||
* of 0, 1, or 2 bytes are allowed. A specification of 0
|
||||
* bytes implies that the field being constructed has the LV
|
||||
* format rather than the TLV format.
|
||||
* @param lengthSize Number of bytes used for the Length (L) field.
|
||||
* Values of 1 or 2 bytes are allowed.
|
||||
*/
|
||||
public TlvConstructor(int typeSize, int lengthSize) {
|
||||
if (typeSize < 0 || typeSize > 2 || lengthSize <= 0 || lengthSize > 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid sizes - typeSize=" + typeSize + ", lengthSize=" + lengthSize);
|
||||
}
|
||||
mTypeSize = typeSize;
|
||||
mLengthSize = lengthSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the byte array to be used to construct the TLV.
|
||||
*
|
||||
* @param array Byte array to be formatted.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor wrap(byte[] array) {
|
||||
mArray = array;
|
||||
mArrayLength = array.length;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a new byte array to be used ot construct a TLV.
|
||||
*
|
||||
* @param capacity The size of the byte array to be allocated.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor allocate(int capacity) {
|
||||
mArray = new byte[capacity];
|
||||
mArrayLength = capacity;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a byte into the TLV with the indicated type. For an LV
|
||||
* formatted structure (i.e. typeLength=0 in {@link TlvConstructor
|
||||
* TlvConstructor(int, int)} ) the type field is ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @param b The byte to be inserted into the structure.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putByte(int type, byte b) {
|
||||
checkLength(1);
|
||||
addHeader(type, 1);
|
||||
mArray[mPosition++] = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a byte array into the TLV with the indicated type. For an LV
|
||||
* formatted structure (i.e. typeLength=0 in {@link TlvConstructor
|
||||
* TlvConstructor(int, int)} ) the type field is ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @param array The array to be copied into the TLV structure.
|
||||
* @param offset Start copying from the array at the specified offset.
|
||||
* @param length Copy the specified number (length) of bytes from the
|
||||
* array.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putByteArray(int type, byte[] array, int offset, int length) {
|
||||
checkLength(length);
|
||||
addHeader(type, length);
|
||||
System.arraycopy(array, offset, mArray, mPosition, length);
|
||||
mPosition += length;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a byte array into the TLV with the indicated type. For an LV
|
||||
* formatted structure (i.e. typeLength=0 in {@link TlvConstructor
|
||||
* TlvConstructor(int, int)} ) the type field is ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @param array The array to be copied (in full) into the TLV structure.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putByteArray(int type, byte[] array) {
|
||||
return putByteArray(type, array, 0, array.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places a zero length element (i.e. Length field = 0) into the TLV.
|
||||
* For an LV formatted structure (i.e. typeLength=0 in
|
||||
* {@link TlvConstructor TlvConstructor(int, int)} ) the type field is
|
||||
* ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putZeroLengthElement(int type) {
|
||||
checkLength(0);
|
||||
addHeader(type, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies short into the TLV with the indicated type. For an LV
|
||||
* formatted structure (i.e. typeLength=0 in {@link TlvConstructor
|
||||
* TlvConstructor(int, int)} ) the type field is ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @param data The short to be inserted into the structure.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putShort(int type, short data) {
|
||||
checkLength(2);
|
||||
addHeader(type, 2);
|
||||
Memory.pokeShort(mArray, mPosition, data, ByteOrder.BIG_ENDIAN);
|
||||
mPosition += 2;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies integer into the TLV with the indicated type. For an LV
|
||||
* formatted structure (i.e. typeLength=0 in {@link TlvConstructor
|
||||
* TlvConstructor(int, int)} ) the type field is ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @param data The integer to be inserted into the structure.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putInt(int type, int data) {
|
||||
checkLength(4);
|
||||
addHeader(type, 4);
|
||||
Memory.pokeInt(mArray, mPosition, data, ByteOrder.BIG_ENDIAN);
|
||||
mPosition += 4;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a String's byte representation into the TLV with the indicated
|
||||
* type. For an LV formatted structure (i.e. typeLength=0 in
|
||||
* {@link TlvConstructor TlvConstructor(int, int)} ) the type field is
|
||||
* ignored.
|
||||
*
|
||||
* @param type The value to be placed into the Type field.
|
||||
* @param data The string whose bytes are to be inserted into the
|
||||
* structure.
|
||||
* @return The constructor to facilitate chaining
|
||||
* {@code ctr.putXXX(..).putXXX(..)}.
|
||||
*/
|
||||
public TlvConstructor putString(int type, String data) {
|
||||
return putByteArray(type, data.getBytes(), 0, data.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constructed TLV formatted byte-array. Note that the
|
||||
* returned array is the fully wrapped (
|
||||
* {@link TlvConstructor#wrap(byte[])}) or allocated (
|
||||
* {@link TlvConstructor#allocate(int)}) array - which isn't necessarily
|
||||
* the actual size of the formatted data. Use
|
||||
* {@link TlvConstructor#getActualLength()} to obtain the size of the
|
||||
* formatted data.
|
||||
*
|
||||
* @return The byte array containing the TLV formatted structure.
|
||||
*/
|
||||
public byte[] getArray() {
|
||||
return mArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the TLV formatted portion of the wrapped or
|
||||
* allocated byte array. The array itself is returned with
|
||||
* {@link TlvConstructor#getArray()}.
|
||||
*
|
||||
* @return The size of the TLV formatted portion of the byte array.
|
||||
*/
|
||||
public int getActualLength() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
private void checkLength(int dataLength) {
|
||||
if (mPosition + mTypeSize + mLengthSize + dataLength > mArrayLength) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
}
|
||||
|
||||
private void addHeader(int type, int length) {
|
||||
if (mTypeSize == 1) {
|
||||
mArray[mPosition] = (byte) type;
|
||||
} else if (mTypeSize == 2) {
|
||||
Memory.pokeShort(mArray, mPosition, (short) type, ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
mPosition += mTypeSize;
|
||||
|
||||
if (mLengthSize == 1) {
|
||||
mArray[mPosition] = (byte) length;
|
||||
} else if (mLengthSize == 2) {
|
||||
Memory.pokeShort(mArray, mPosition, (short) length, ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
mPosition += mLengthSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class used when iterating over a TLV formatted byte-array. Use
|
||||
* {@link TlvIterable} to iterate over array. A {@link TlvElement}
|
||||
* represents each entry in a TLV formatted byte-array.
|
||||
*/
|
||||
public static class TlvElement {
|
||||
/**
|
||||
* The Type (T) field of the current TLV element. Note that for LV
|
||||
* formatted byte-arrays (i.e. TLV whose Type/T size is 0) the value of
|
||||
* this field is undefined.
|
||||
*/
|
||||
public int mType;
|
||||
|
||||
/**
|
||||
* The Length (L) field of the current TLV element.
|
||||
*/
|
||||
public int mLength;
|
||||
|
||||
/**
|
||||
* The Value (V) field - a raw byte array representing the current TLV
|
||||
* element where the entry starts at {@link TlvElement#mOffset}.
|
||||
*/
|
||||
public byte[] mRefArray;
|
||||
|
||||
/**
|
||||
* The offset to be used into {@link TlvElement#mRefArray} to access the
|
||||
* raw data representing the current TLV element.
|
||||
*/
|
||||
public int mOffset;
|
||||
|
||||
private TlvElement(int type, int length, byte[] refArray, int offset) {
|
||||
mType = type;
|
||||
mLength = length;
|
||||
mRefArray = refArray;
|
||||
mOffset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to return a byte representation of a TLV element of
|
||||
* length 1. Note: an attempt to call this function on a TLV item whose
|
||||
* {@link TlvElement#mLength} is != 1 will result in an exception.
|
||||
*
|
||||
* @return byte representation of current TLV element.
|
||||
*/
|
||||
public byte getByte() {
|
||||
if (mLength != 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Accesing a byte from a TLV element of length " + mLength);
|
||||
}
|
||||
return mRefArray[mOffset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to return a short representation of a TLV element of
|
||||
* length 2. Note: an attempt to call this function on a TLV item whose
|
||||
* {@link TlvElement#mLength} is != 2 will result in an exception.
|
||||
*
|
||||
* @return short representation of current TLV element.
|
||||
*/
|
||||
public short getShort() {
|
||||
if (mLength != 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"Accesing a short from a TLV element of length " + mLength);
|
||||
}
|
||||
return Memory.peekShort(mRefArray, mOffset, ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to return an integer representation of a TLV element
|
||||
* of length 4. Note: an attempt to call this function on a TLV item
|
||||
* whose {@link TlvElement#mLength} is != 4 will result in an exception.
|
||||
*
|
||||
* @return integer representation of current TLV element.
|
||||
*/
|
||||
public int getInt() {
|
||||
if (mLength != 4) {
|
||||
throw new IllegalArgumentException(
|
||||
"Accesing an int from a TLV element of length " + mLength);
|
||||
}
|
||||
return Memory.peekInt(mRefArray, mOffset, ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to return a String representation of a TLV element.
|
||||
*
|
||||
* @return String repersentation of the current TLV element.
|
||||
*/
|
||||
public String getString() {
|
||||
return new String(mRefArray, mOffset, mLength);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to iterate over a TLV formatted byte-array.
|
||||
*/
|
||||
public static class TlvIterable implements Iterable<TlvElement> {
|
||||
private int mTypeSize;
|
||||
private int mLengthSize;
|
||||
private byte[] mArray;
|
||||
private int mArrayLength;
|
||||
|
||||
/**
|
||||
* Constructs a TlvIterable object - specifying the format of the TLV
|
||||
* (the sizes of the Type and Length fields), and the byte array whose
|
||||
* data is to be parsed.
|
||||
*
|
||||
* @param typeSize Number of bytes used for the Type (T) field. Valid
|
||||
* values are 0 (i.e. indicating the format is LV rather than
|
||||
* TLV), 1, and 2 bytes.
|
||||
* @param lengthSize Number of bytes sued for the Length (L) field.
|
||||
* Values values are 1 or 2 bytes.
|
||||
* @param array The TLV formatted byte-array to parse.
|
||||
* @param length The number of bytes of the array to be used in the
|
||||
* parsing.
|
||||
*/
|
||||
public TlvIterable(int typeSize, int lengthSize, byte[] array, int length) {
|
||||
if (typeSize < 0 || typeSize > 2 || lengthSize <= 0 || lengthSize > 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid sizes - typeSize=" + typeSize + ", lengthSize=" + lengthSize);
|
||||
}
|
||||
mTypeSize = typeSize;
|
||||
mLengthSize = lengthSize;
|
||||
mArray = array;
|
||||
mArrayLength = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out a parsed representation of the TLV-formatted byte array.
|
||||
* Whenever possible bytes, shorts, and integer are printed out (for
|
||||
* fields whose length is 1, 2, or 4 respectively).
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("[");
|
||||
boolean first = true;
|
||||
for (TlvElement tlv : this) {
|
||||
if (!first) {
|
||||
builder.append(",");
|
||||
}
|
||||
first = false;
|
||||
builder.append(" (");
|
||||
if (mTypeSize != 0) {
|
||||
builder.append("T=" + tlv.mType + ",");
|
||||
}
|
||||
builder.append("L=" + tlv.mLength + ") ");
|
||||
if (tlv.mLength == 0) {
|
||||
builder.append("<null>");
|
||||
} else if (tlv.mLength == 1) {
|
||||
builder.append(tlv.getByte());
|
||||
} else if (tlv.mLength == 2) {
|
||||
builder.append(tlv.getShort());
|
||||
} else if (tlv.mLength == 4) {
|
||||
builder.append(tlv.getInt());
|
||||
} else {
|
||||
builder.append("<bytes>");
|
||||
}
|
||||
if (tlv.mLength != 0) {
|
||||
builder.append(" (S='" + tlv.getString() + "')");
|
||||
}
|
||||
}
|
||||
builder.append("]");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to step through a TLV formatted byte-array. The
|
||||
* individual elements returned by the iterator are {@link TlvElement}.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<TlvElement> iterator() {
|
||||
return new Iterator<TlvElement>() {
|
||||
private int mOffset = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return mOffset < mArrayLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TlvElement next() {
|
||||
int type = 0;
|
||||
if (mTypeSize == 1) {
|
||||
type = mArray[mOffset];
|
||||
} else if (mTypeSize == 2) {
|
||||
type = Memory.peekShort(mArray, mOffset, ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
mOffset += mTypeSize;
|
||||
|
||||
int length = 0;
|
||||
if (mLengthSize == 1) {
|
||||
length = mArray[mOffset];
|
||||
} else if (mLengthSize == 2) {
|
||||
length = Memory.peekShort(mArray, mOffset, ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
mOffset += mLengthSize;
|
||||
|
||||
TlvElement tlv = new TlvElement(type, length, mArray, mOffset);
|
||||
mOffset += length;
|
||||
return tlv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
201
wifi/java/android/net/wifi/nan/WifiNanEventListener.java
Normal file
201
wifi/java/android/net/wifi/nan/WifiNanEventListener.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Base class for NAN events callbacks. Should be extended by applications
|
||||
* wanting notifications. These are callbacks applying to the NAN connection as
|
||||
* a whole - not to specific publish or subscribe sessions - for that see
|
||||
* {@link WifiNanSessionListener}.
|
||||
* <p>
|
||||
* During registration specify which specific events are desired using a set of
|
||||
* {@code NanEventListener.LISTEN_*} flags OR'd together. Only those events will
|
||||
* be delivered to the registered listener. Override those callbacks
|
||||
* {@code NanEventListener.on*} for the registered events.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class WifiNanEventListener {
|
||||
private static final String TAG = "WifiNanEventListener";
|
||||
private static final boolean DBG = true;
|
||||
private static final boolean VDBG = false; // STOPSHIP if true
|
||||
|
||||
/**
|
||||
* Configuration completion callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanEventListener#onConfigCompleted(ConfigRequest)}.
|
||||
*/
|
||||
public static final int LISTEN_CONFIG_COMPLETED = 0x1 << 0;
|
||||
|
||||
/**
|
||||
* Configuration failed callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanEventListener#onConfigFailed(int)}.
|
||||
*/
|
||||
public static final int LISTEN_CONFIG_FAILED = 0x1 << 1;
|
||||
|
||||
/**
|
||||
* NAN cluster is down callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanEventListener#onNanDown(int)}.
|
||||
*/
|
||||
public static final int LISTEN_NAN_DOWN = 0x1 << 2;
|
||||
|
||||
/**
|
||||
* NAN identity has changed event registration flag. This may be due to
|
||||
* joining a cluster, starting a cluster, or discovery interface change. The
|
||||
* implication is that peers you've been communicating with may no longer
|
||||
* recognize you and you need to re-establish your identity. Corresponding
|
||||
* callback is {@link WifiNanEventListener#onIdentityChanged()}.
|
||||
*/
|
||||
public static final int LISTEN_IDENTITY_CHANGED = 0x1 << 3;
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
/**
|
||||
* Constructs a {@link WifiNanEventListener} using the looper of the current
|
||||
* thread. I.e. all callbacks will be delivered on the current thread.
|
||||
*/
|
||||
public WifiNanEventListener() {
|
||||
this(Looper.myLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link WifiNanEventListener} using the specified looper. I.e.
|
||||
* all callbacks will delivered on the thread of the specified looper.
|
||||
*
|
||||
* @param looper The looper on which to execute the callbacks.
|
||||
*/
|
||||
public WifiNanEventListener(Looper looper) {
|
||||
if (VDBG) Log.v(TAG, "ctor: looper=" + looper);
|
||||
mHandler = new Handler(looper) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
|
||||
switch (msg.what) {
|
||||
case LISTEN_CONFIG_COMPLETED:
|
||||
WifiNanEventListener.this.onConfigCompleted((ConfigRequest) msg.obj);
|
||||
break;
|
||||
case LISTEN_CONFIG_FAILED:
|
||||
WifiNanEventListener.this.onConfigFailed(msg.arg1);
|
||||
break;
|
||||
case LISTEN_NAN_DOWN:
|
||||
WifiNanEventListener.this.onNanDown(msg.arg1);
|
||||
break;
|
||||
case LISTEN_IDENTITY_CHANGED:
|
||||
WifiNanEventListener.this.onIdentityChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when NAN configuration is completed. Event will only be delivered
|
||||
* if registered using {@link WifiNanEventListener#LISTEN_CONFIG_COMPLETED}. A
|
||||
* dummy (empty implementation printing out a warning). Make sure to
|
||||
* override if registered.
|
||||
*
|
||||
* @param completedConfig The actual configuration request which was
|
||||
* completed. Note that it may be different from that requested
|
||||
* by the application. The service combines configuration
|
||||
* requests from all applications.
|
||||
*/
|
||||
public void onConfigCompleted(ConfigRequest completedConfig) {
|
||||
Log.w(TAG, "onConfigCompleted: called in stub - override if interested or disable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when NAN configuration failed. Event will only be delivered if
|
||||
* registered using {@link WifiNanEventListener#LISTEN_CONFIG_FAILED}. A dummy
|
||||
* (empty implementation printing out a warning). Make sure to override if
|
||||
* registered.
|
||||
*
|
||||
* @param reason Failure reason code, see {@code NanSessionListener.FAIL_*}.
|
||||
*/
|
||||
public void onConfigFailed(int reason) {
|
||||
Log.w(TAG, "onConfigFailed: called in stub - override if interested or disable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when NAN cluster is down. Event will only be delivered if
|
||||
* registered using {@link WifiNanEventListener#LISTEN_NAN_DOWN}. A dummy (empty
|
||||
* implementation printing out a warning). Make sure to override if
|
||||
* registered.
|
||||
*
|
||||
* @param reason Reason code for event, see {@code NanSessionListener.FAIL_*}.
|
||||
*/
|
||||
public void onNanDown(int reason) {
|
||||
Log.w(TAG, "onNanDown: called in stub - override if interested or disable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when NAN identity has changed. This may be due to joining a
|
||||
* cluster, starting a cluster, or discovery interface change. The
|
||||
* implication is that peers you've been communicating with may no longer
|
||||
* recognize you and you need to re-establish your identity. Event will only
|
||||
* be delivered if registered using
|
||||
* {@link WifiNanEventListener#LISTEN_IDENTITY_CHANGED}. A dummy (empty
|
||||
* implementation printing out a warning). Make sure to override if
|
||||
* registered.
|
||||
*/
|
||||
public void onIdentityChanged() {
|
||||
if (VDBG) Log.v(TAG, "onIdentityChanged: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public IWifiNanEventListener callback = new IWifiNanEventListener.Stub() {
|
||||
@Override
|
||||
public void onConfigCompleted(ConfigRequest completedConfig) {
|
||||
if (VDBG) Log.v(TAG, "onConfigCompleted: configRequest=" + completedConfig);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_CONFIG_COMPLETED);
|
||||
msg.obj = completedConfig;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigFailed(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onConfigFailed: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_CONFIG_FAILED);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNanDown(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onNanDown: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_NAN_DOWN);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIdentityChanged() {
|
||||
if (VDBG) Log.v(TAG, "onIdentityChanged");
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_IDENTITY_CHANGED);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
333
wifi/java/android/net/wifi/nan/WifiNanManager.java
Normal file
333
wifi/java/android/net/wifi/nan/WifiNanManager.java
Normal file
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class provides the primary API for managing Wi-Fi NAN operation:
|
||||
* including discovery and data-links. Get an instance of this class by calling
|
||||
* {@link android.content.Context#getSystemService(String)
|
||||
* Context.getSystemService(Context.WIFI_NAN_SERVICE)}.
|
||||
* <p>
|
||||
* The class provides access to:
|
||||
* <ul>
|
||||
* <li>Configure a NAN connection and register for events.
|
||||
* <li>Create publish and subscribe sessions.
|
||||
* <li>Create NAN network specifier to be used to create a NAN network.
|
||||
* </ul>
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class WifiNanManager {
|
||||
private static final String TAG = "WifiNanManager";
|
||||
private static final boolean DBG = true;
|
||||
private static final boolean VDBG = false; // STOPSHIP if true
|
||||
|
||||
private IBinder mBinder;
|
||||
|
||||
private IWifiNanManager mService;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public WifiNanManager(IWifiNanManager service) {
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-connect to the Wi-Fi NAN service - enabling the application to execute
|
||||
* {@link WifiNanManager} APIs. Application don't normally need to call this
|
||||
* API since it is executed in the constructor. However, applications which
|
||||
* have explicitly {@link WifiNanManager#disconnect()} need to call this
|
||||
* function to re-connect.
|
||||
*
|
||||
* @param listener A listener extended from {@link WifiNanEventListener}.
|
||||
* @param events The set of events to be delivered to the {@code listener}.
|
||||
* OR'd event flags from {@link WifiNanEventListener
|
||||
* NanEventListener.LISTEN*}.
|
||||
*/
|
||||
public void connect(WifiNanEventListener listener, int events) {
|
||||
try {
|
||||
if (VDBG) Log.v(TAG, "connect()");
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("Invalid listener - must not be null");
|
||||
}
|
||||
if (mBinder == null) {
|
||||
mBinder = new Binder();
|
||||
}
|
||||
mService.connect(mBinder, listener.callback, events);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "connect RemoteException (FYI - ignoring): " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the Wi-Fi NAN service and destroy all outstanding
|
||||
* operations - i.e. all publish and subscribes are terminated, any
|
||||
* outstanding data-link is shut-down, and all requested NAN configurations
|
||||
* are cancelled.
|
||||
* <p>
|
||||
* An application may then re-connect using
|
||||
* {@link WifiNanManager#connect(WifiNanEventListener, int)} .
|
||||
*/
|
||||
public void disconnect() {
|
||||
try {
|
||||
if (VDBG) Log.v(TAG, "disconnect()");
|
||||
mService.disconnect(mBinder);
|
||||
mBinder = null;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "disconnect RemoteException (FYI - ignoring): " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a NAN configuration, specified by {@link ConfigRequest}. Note
|
||||
* that NAN is a shared resource and the device can only be a member of a
|
||||
* single cluster. Thus the service may merge configuration requests from
|
||||
* multiple applications and configure NAN differently from individual
|
||||
* requests.
|
||||
* <p>
|
||||
* The {@link WifiNanEventListener#onConfigCompleted(ConfigRequest)} will be
|
||||
* called when configuration is completed (if a listener is registered for
|
||||
* this specific event).
|
||||
*
|
||||
* @param configRequest The requested NAN configuration.
|
||||
*/
|
||||
public void requestConfig(ConfigRequest configRequest) {
|
||||
if (VDBG) Log.v(TAG, "requestConfig(): configRequest=" + configRequest);
|
||||
try {
|
||||
mService.requestConfig(configRequest);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "requestConfig RemoteException (FYI - ignoring): " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a NAN publish session. The results of the publish session
|
||||
* operation will result in callbacks to the indicated listener:
|
||||
* {@link WifiNanSessionListener NanSessionListener.on*}.
|
||||
*
|
||||
* @param publishData The {@link PublishData} specifying the contents of the
|
||||
* publish session.
|
||||
* @param publishSettings The {@link PublishSettings} specifying the
|
||||
* settings for the publish session.
|
||||
* @param listener The {@link WifiNanSessionListener} derived objects to be used
|
||||
* for the event callbacks specified by {@code events}.
|
||||
* @param events The list of events to be delivered to the {@code listener}
|
||||
* object. An OR'd value of {@link WifiNanSessionListener
|
||||
* NanSessionListener.LISTEN_*}.
|
||||
* @return The {@link WifiNanPublishSession} which can be used to further
|
||||
* control the publish session.
|
||||
*/
|
||||
public WifiNanPublishSession publish(PublishData publishData, PublishSettings publishSettings,
|
||||
WifiNanSessionListener listener, int events) {
|
||||
return publishRaw(publishData, publishSettings, listener,
|
||||
events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as publish(*) but does not modify the event flag
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public WifiNanPublishSession publishRaw(PublishData publishData,
|
||||
PublishSettings publishSettings, WifiNanSessionListener listener, int events) {
|
||||
if (VDBG) Log.v(TAG, "publish(): data='" + publishData + "', settings=" + publishSettings);
|
||||
|
||||
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_UNSOLICITED
|
||||
&& publishData.mRxFilterLength != 0) {
|
||||
throw new IllegalArgumentException("Invalid publish data & settings: UNSOLICITED "
|
||||
+ "publishes (active) can't have an Rx filter");
|
||||
}
|
||||
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_SOLICITED
|
||||
&& publishData.mTxFilterLength != 0) {
|
||||
throw new IllegalArgumentException("Invalid publish data & settings: SOLICITED "
|
||||
+ "publishes (passive) can't have a Tx filter");
|
||||
}
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("Invalid listener - must not be null");
|
||||
}
|
||||
|
||||
int sessionId;
|
||||
|
||||
try {
|
||||
sessionId = mService.createSession(listener.callback, events);
|
||||
if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId);
|
||||
mService.publish(sessionId, publishData, publishSettings);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "createSession/publish RemoteException: " + e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new WifiNanPublishSession(this, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public void publish(int sessionId, PublishData publishData, PublishSettings publishSettings) {
|
||||
if (VDBG) Log.v(TAG, "publish(): data='" + publishData + "', settings=" + publishSettings);
|
||||
|
||||
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_UNSOLICITED
|
||||
&& publishData.mRxFilterLength != 0) {
|
||||
throw new IllegalArgumentException("Invalid publish data & settings: UNSOLICITED "
|
||||
+ "publishes (active) can't have an Rx filter");
|
||||
}
|
||||
if (publishSettings.mPublishType == PublishSettings.PUBLISH_TYPE_SOLICITED
|
||||
&& publishData.mTxFilterLength != 0) {
|
||||
throw new IllegalArgumentException("Invalid publish data & settings: SOLICITED "
|
||||
+ "publishes (passive) can't have a Tx filter");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.publish(sessionId, publishData, publishSettings);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "publish RemoteException: " + e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Request a NAN subscribe session. The results of the subscribe session
|
||||
* operation will result in callbacks to the indicated listener:
|
||||
* {@link WifiNanSessionListener NanSessionListener.on*}.
|
||||
*
|
||||
* @param subscribeData The {@link SubscribeData} specifying the contents of
|
||||
* the subscribe session.
|
||||
* @param subscribeSettings The {@link SubscribeSettings} specifying the
|
||||
* settings for the subscribe session.
|
||||
* @param listener The {@link WifiNanSessionListener} derived objects to be used
|
||||
* for the event callbacks specified by {@code events}.
|
||||
* @param events The list of events to be delivered to the {@code listener}
|
||||
* object. An OR'd value of {@link WifiNanSessionListener
|
||||
* NanSessionListener.LISTEN_*}.
|
||||
* @return The {@link WifiNanSubscribeSession} which can be used to further
|
||||
* control the subscribe session.
|
||||
*/
|
||||
public WifiNanSubscribeSession subscribe(SubscribeData subscribeData,
|
||||
SubscribeSettings subscribeSettings,
|
||||
WifiNanSessionListener listener, int events) {
|
||||
return subscribeRaw(subscribeData, subscribeSettings, listener,
|
||||
events | WifiNanSessionListener.LISTEN_HIDDEN_FLAGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as subscribe(*) but does not modify the event flag
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public WifiNanSubscribeSession subscribeRaw(SubscribeData subscribeData,
|
||||
SubscribeSettings subscribeSettings, WifiNanSessionListener listener, int events) {
|
||||
if (VDBG) {
|
||||
Log.v(TAG, "subscribe(): data='" + subscribeData + "', settings=" + subscribeSettings);
|
||||
}
|
||||
|
||||
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_ACTIVE
|
||||
&& subscribeData.mRxFilterLength != 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid subscribe data & settings: ACTIVE subscribes can't have an Rx filter");
|
||||
}
|
||||
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE
|
||||
&& subscribeData.mTxFilterLength != 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid subscribe data & settings: PASSIVE subscribes can't have a Tx filter");
|
||||
}
|
||||
|
||||
int sessionId;
|
||||
|
||||
try {
|
||||
sessionId = mService.createSession(listener.callback, events);
|
||||
if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId);
|
||||
mService.subscribe(sessionId, subscribeData, subscribeSettings);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "createSession/subscribe RemoteException: " + e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new WifiNanSubscribeSession(this, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public void subscribe(int sessionId, SubscribeData subscribeData,
|
||||
SubscribeSettings subscribeSettings) {
|
||||
if (VDBG) {
|
||||
Log.v(TAG, "subscribe(): data='" + subscribeData + "', settings=" + subscribeSettings);
|
||||
}
|
||||
|
||||
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_ACTIVE
|
||||
&& subscribeData.mRxFilterLength != 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid subscribe data & settings: ACTIVE subscribes can't have an Rx filter");
|
||||
}
|
||||
if (subscribeSettings.mSubscribeType == SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE
|
||||
&& subscribeData.mTxFilterLength != 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid subscribe data & settings: PASSIVE subscribes can't have a Tx filter");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.subscribe(sessionId, subscribeData, subscribeSettings);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "subscribe RemoteException: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public void stopSession(int sessionId) {
|
||||
if (DBG) Log.d(TAG, "Stop NAN session #" + sessionId);
|
||||
|
||||
try {
|
||||
mService.stopSession(sessionId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "stopSession RemoteException (FYI - ignoring): " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public void destroySession(int sessionId) {
|
||||
if (DBG) Log.d(TAG, "Destroy NAN session #" + sessionId);
|
||||
|
||||
try {
|
||||
mService.destroySession(sessionId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "destroySession RemoteException (FYI - ignoring): " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength) {
|
||||
try {
|
||||
if (VDBG) {
|
||||
Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId
|
||||
+ ", messageLength=" + messageLength);
|
||||
}
|
||||
mService.sendMessage(sessionId, peerId, message, messageLength);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
47
wifi/java/android/net/wifi/nan/WifiNanPublishSession.java
Normal file
47
wifi/java/android/net/wifi/nan/WifiNanPublishSession.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
/**
|
||||
* A representation of a NAN publish session. Created when
|
||||
* {@link WifiNanManager#publish(PublishData, PublishSettings, WifiNanSessionListener, int)}
|
||||
* is executed. The object can be used to stop and re-start (re-configure) the
|
||||
* publish session.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class WifiNanPublishSession extends WifiNanSession {
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public WifiNanPublishSession(WifiNanManager manager, int sessionId) {
|
||||
super(manager, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart/re-configure the publish session. Note that the
|
||||
* {@link WifiNanSessionListener} is not replaced - the same listener used at
|
||||
* creation is still used.
|
||||
*
|
||||
* @param publishData The data ({@link PublishData}) to publish.
|
||||
* @param publishSettings The settings ({@link PublishSettings}) of the
|
||||
* publish session.
|
||||
*/
|
||||
public void publish(PublishData publishData, PublishSettings publishSettings) {
|
||||
mManager.publish(mSessionId, publishData, publishSettings);
|
||||
}
|
||||
}
|
||||
110
wifi/java/android/net/wifi/nan/WifiNanSession.java
Normal file
110
wifi/java/android/net/wifi/nan/WifiNanSession.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A representation of a single publish or subscribe NAN session. This object
|
||||
* will not be created directly - only its child classes are available:
|
||||
* {@link WifiNanPublishSession} and {@link WifiNanSubscribeSession}.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class WifiNanSession {
|
||||
private static final String TAG = "WifiNanSession";
|
||||
private static final boolean DBG = true;
|
||||
private static final boolean VDBG = false; // STOPSHIP if true
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
protected WifiNanManager mManager;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
protected int mSessionId;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
private boolean mDestroyed;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public WifiNanSession(WifiNanManager manager, int sessionId) {
|
||||
if (VDBG) Log.v(TAG, "New client created: manager=" + manager + ", sessionId=" + sessionId);
|
||||
|
||||
mManager = manager;
|
||||
mSessionId = sessionId;
|
||||
mDestroyed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the current publish or subscribe session - i.e. stop
|
||||
* transmitting packet on-air (for an active session) or listening for
|
||||
* matches (for a passive session). Note that the session may still receive
|
||||
* incoming messages and may be re-configured/re-started at a later time.
|
||||
*/
|
||||
public void stop() {
|
||||
mManager.stopSession(mSessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the current publish or subscribe session. Performs a
|
||||
* {@link WifiNanSession#stop()} function but in addition destroys the session -
|
||||
* it will not be able to receive any messages or to be restarted at a later
|
||||
* time.
|
||||
*/
|
||||
public void destroy() {
|
||||
mManager.destroySession(mSessionId);
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (!mDestroyed) {
|
||||
Log.w(TAG, "WifiNanSession mSessionId=" + mSessionId
|
||||
+ " was not explicitly destroyed. The session may use resources until "
|
||||
+ "destroyed so step should be done explicitly");
|
||||
}
|
||||
destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the specified destination. Message transmission is
|
||||
* part of the current discovery session - i.e. executed subsequent to a
|
||||
* publish/subscribe
|
||||
* {@link WifiNanSessionListener#onMatch(int, byte[], int, byte[], int)}
|
||||
* event.
|
||||
*
|
||||
* @param peerId The peer's ID for the message. Must be a result of an
|
||||
* {@link WifiNanSessionListener#onMatch(int, byte[], int, byte[], int)}
|
||||
* event.
|
||||
* @param message The message to be transmitted.
|
||||
* @param messageLength The number of bytes from the {@code message} to be
|
||||
* transmitted.
|
||||
*/
|
||||
public void sendMessage(int peerId, byte[] message, int messageLength) {
|
||||
mManager.sendMessage(mSessionId, peerId, message, messageLength);
|
||||
}
|
||||
}
|
||||
437
wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
Normal file
437
wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
Normal file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Base class for NAN session events callbacks. Should be extended by
|
||||
* applications wanting notifications. The callbacks are registered when a
|
||||
* publish or subscribe session is created using
|
||||
* {@link WifiNanManager#publish(PublishData, PublishSettings, WifiNanSessionListener, int)}
|
||||
* or
|
||||
* {@link WifiNanManager#subscribe(SubscribeData, SubscribeSettings, WifiNanSessionListener, int)}
|
||||
* . These are callbacks applying to a specific NAN session. Events
|
||||
* corresponding to the NAN link are delivered using {@link WifiNanEventListener}.
|
||||
* <p>
|
||||
* A single listener is registered at session creation - it cannot be replaced.
|
||||
* <p>
|
||||
* During registration specify which specific events are desired using a set of
|
||||
* {@code NanSessionListener.LISTEN_*} flags OR'd together. Only those events
|
||||
* will be delivered to the registered listener. Override those callbacks
|
||||
* {@code NanSessionListener.on*} for the registered events.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class WifiNanSessionListener {
|
||||
private static final String TAG = "WifiNanSessionListener";
|
||||
private static final boolean DBG = true;
|
||||
private static final boolean VDBG = false; // STOPSHIP if true
|
||||
|
||||
/**
|
||||
* Publish fail callback event registration flag. Corresponding callback is
|
||||
* {@link WifiNanSessionListener#onPublishFail(int)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_PUBLISH_FAIL = 0x1 << 0;
|
||||
|
||||
/**
|
||||
* Publish terminated callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanSessionListener#onPublishTerminated(int)}.
|
||||
*/
|
||||
public static final int LISTEN_PUBLISH_TERMINATED = 0x1 << 1;
|
||||
|
||||
/**
|
||||
* Subscribe fail callback event registration flag. Corresponding callback
|
||||
* is {@link WifiNanSessionListener#onSubscribeFail(int)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_SUBSCRIBE_FAIL = 0x1 << 2;
|
||||
|
||||
/**
|
||||
* Subscribe terminated callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanSessionListener#onSubscribeTerminated(int)}.
|
||||
*/
|
||||
public static final int LISTEN_SUBSCRIBE_TERMINATED = 0x1 << 3;
|
||||
|
||||
/**
|
||||
* Match (discovery: publish or subscribe) callback event registration flag.
|
||||
* Corresponding callback is
|
||||
* {@link WifiNanSessionListener#onMatch(int, byte[], int, byte[], int)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_MATCH = 0x1 << 4;
|
||||
|
||||
/**
|
||||
* Message sent successfully callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanSessionListener#onMessageSendSuccess()}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_MESSAGE_SEND_SUCCESS = 0x1 << 5;
|
||||
|
||||
/**
|
||||
* Message sending failure callback event registration flag. Corresponding
|
||||
* callback is {@link WifiNanSessionListener#onMessageSendFail(int)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_MESSAGE_SEND_FAIL = 0x1 << 6;
|
||||
|
||||
/**
|
||||
* Message received callback event registration flag. Corresponding callback
|
||||
* is {@link WifiNanSessionListener#onMessageReceived(int, byte[], int)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_MESSAGE_RECEIVED = 0x1 << 7;
|
||||
|
||||
/**
|
||||
* List of hidden events: which are mandatory - i.e. they will be added to
|
||||
* every request.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int LISTEN_HIDDEN_FLAGS = LISTEN_PUBLISH_FAIL | LISTEN_SUBSCRIBE_FAIL
|
||||
| LISTEN_MATCH | LISTEN_MESSAGE_SEND_SUCCESS | LISTEN_MESSAGE_SEND_FAIL
|
||||
| LISTEN_MESSAGE_RECEIVED;
|
||||
|
||||
/**
|
||||
* Failure reason flag for {@link WifiNanEventListener} and
|
||||
* {@link WifiNanSessionListener} callbacks. Indicates no resources to execute
|
||||
* the requested operation.
|
||||
*/
|
||||
public static final int FAIL_REASON_NO_RESOURCES = 0;
|
||||
|
||||
/**
|
||||
* Failure reason flag for {@link WifiNanEventListener} and
|
||||
* {@link WifiNanSessionListener} callbacks. Indicates invalid argument in the
|
||||
* requested operation.
|
||||
*/
|
||||
public static final int FAIL_REASON_INVALID_ARGS = 1;
|
||||
|
||||
/**
|
||||
* Failure reason flag for {@link WifiNanEventListener} and
|
||||
* {@link WifiNanSessionListener} callbacks. Indicates a message is transmitted
|
||||
* without a match (i.e. a discovery) occurring first.
|
||||
*/
|
||||
public static final int FAIL_REASON_NO_MATCH_SESSION = 2;
|
||||
|
||||
/**
|
||||
* Failure reason flag for {@link WifiNanEventListener} and
|
||||
* {@link WifiNanSessionListener} callbacks. Indicates an unspecified error
|
||||
* occurred during the operation.
|
||||
*/
|
||||
public static final int FAIL_REASON_OTHER = 3;
|
||||
|
||||
/**
|
||||
* Failure reason flag for
|
||||
* {@link WifiNanSessionListener#onPublishTerminated(int)} and
|
||||
* {@link WifiNanSessionListener#onSubscribeTerminated(int)} callbacks.
|
||||
* Indicates that publish or subscribe session is done - i.e. all the
|
||||
* requested operations (per {@link PublishSettings} or
|
||||
* {@link SubscribeSettings}) have been executed.
|
||||
*/
|
||||
public static final int TERMINATE_REASON_DONE = 0;
|
||||
|
||||
/**
|
||||
* Failure reason flag for
|
||||
* {@link WifiNanSessionListener#onPublishTerminated(int)} and
|
||||
* {@link WifiNanSessionListener#onSubscribeTerminated(int)} callbacks.
|
||||
* Indicates that publish or subscribe session is terminated due to a
|
||||
* failure.
|
||||
*/
|
||||
public static final int TERMINATE_REASON_FAIL = 1;
|
||||
|
||||
private static final String MESSAGE_BUNDLE_KEY_PEER_ID = "peer_id";
|
||||
private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
|
||||
private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
/**
|
||||
* Constructs a {@link WifiNanSessionListener} using the looper of the current
|
||||
* thread. I.e. all callbacks will be delivered on the current thread.
|
||||
*/
|
||||
public WifiNanSessionListener() {
|
||||
this(Looper.myLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link WifiNanSessionListener} using the specified looper. I.e.
|
||||
* all callbacks will delivered on the thread of the specified looper.
|
||||
*
|
||||
* @param looper The looper on which to execute the callbacks.
|
||||
*/
|
||||
public WifiNanSessionListener(Looper looper) {
|
||||
if (VDBG) Log.v(TAG, "ctor: looper=" + looper);
|
||||
mHandler = new Handler(looper) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
|
||||
switch (msg.what) {
|
||||
case LISTEN_PUBLISH_FAIL:
|
||||
WifiNanSessionListener.this.onPublishFail(msg.arg1);
|
||||
break;
|
||||
case LISTEN_PUBLISH_TERMINATED:
|
||||
WifiNanSessionListener.this.onPublishTerminated(msg.arg1);
|
||||
break;
|
||||
case LISTEN_SUBSCRIBE_FAIL:
|
||||
WifiNanSessionListener.this.onSubscribeFail(msg.arg1);
|
||||
break;
|
||||
case LISTEN_SUBSCRIBE_TERMINATED:
|
||||
WifiNanSessionListener.this.onSubscribeTerminated(msg.arg1);
|
||||
break;
|
||||
case LISTEN_MATCH:
|
||||
WifiNanSessionListener.this.onMatch(
|
||||
msg.getData().getInt(MESSAGE_BUNDLE_KEY_PEER_ID),
|
||||
msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE), msg.arg1,
|
||||
msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2), msg.arg2);
|
||||
break;
|
||||
case LISTEN_MESSAGE_SEND_SUCCESS:
|
||||
WifiNanSessionListener.this.onMessageSendSuccess();
|
||||
break;
|
||||
case LISTEN_MESSAGE_SEND_FAIL:
|
||||
WifiNanSessionListener.this.onMessageSendFail(msg.arg1);
|
||||
break;
|
||||
case LISTEN_MESSAGE_RECEIVED:
|
||||
WifiNanSessionListener.this.onMessageReceived(msg.arg2,
|
||||
msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE), msg.arg1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a publish operation fails. It is dummy method (empty
|
||||
* implementation printing out a log message). Override to implement your
|
||||
* custom response.
|
||||
*
|
||||
* @param reason The failure reason using {@code NanSessionListener.FAIL_*}
|
||||
* codes.
|
||||
*/
|
||||
public void onPublishFail(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onPublishFail: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a publish operation terminates. Event will only be delivered
|
||||
* if registered using {@link WifiNanSessionListener#LISTEN_PUBLISH_TERMINATED}.
|
||||
* A dummy (empty implementation printing out a warning). Make sure to
|
||||
* override if registered.
|
||||
*
|
||||
* @param reason The termination reason using
|
||||
* {@code NanSessionListener.TERMINATE_*} codes.
|
||||
*/
|
||||
public void onPublishTerminated(int reason) {
|
||||
Log.w(TAG, "onPublishTerminated: called in stub - override if interested or disable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a subscribe operation fails. It is dummy method (empty
|
||||
* implementation printing out a log message). Override to implement your
|
||||
* custom response.
|
||||
*
|
||||
* @param reason The failure reason using {@code NanSessionListener.FAIL_*}
|
||||
* codes.
|
||||
*/
|
||||
public void onSubscribeFail(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onSubscribeFail: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a subscribe operation terminates. Event will only be
|
||||
* delivered if registered using
|
||||
* {@link WifiNanSessionListener#LISTEN_SUBSCRIBE_TERMINATED}. A dummy (empty
|
||||
* implementation printing out a warning). Make sure to override if
|
||||
* registered.
|
||||
*
|
||||
* @param reason The termination reason using
|
||||
* {@code NanSessionListener.TERMINATE_*} codes.
|
||||
*/
|
||||
public void onSubscribeTerminated(int reason) {
|
||||
Log.w(TAG, "onSubscribeTerminated: called in stub - override if interested or disable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a discovery (publish or subscribe) operation results in a
|
||||
* match - i.e. when a peer is discovered. It is dummy method (empty
|
||||
* implementation printing out a log message). Override to implement your
|
||||
* custom response.
|
||||
*
|
||||
* @param peerId The ID of the peer matching our discovery operation.
|
||||
* @param serviceSpecificInfo The service specific information (arbitrary
|
||||
* byte array) provided by the peer as part of its discovery
|
||||
* packet.
|
||||
* @param serviceSpecificInfoLength The length of the service specific
|
||||
* information array.
|
||||
* @param matchFilter The filter (Tx on advertiser and Rx on listener) which
|
||||
* resulted in this match.
|
||||
* @param matchFilterLength The length of the match filter array.
|
||||
*/
|
||||
public void onMatch(int peerId, byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) {
|
||||
if (VDBG) Log.v(TAG, "onMatch: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message is transmitted successfully - i.e. when we know
|
||||
* that it was received successfully (corresponding to an ACK being
|
||||
* received). It is dummy method (empty implementation printing out a log
|
||||
* message). Override to implement your custom response.
|
||||
* <p>
|
||||
* Note that either this callback or
|
||||
* {@link WifiNanSessionListener#onMessageSendFail(int)} will be received -
|
||||
* never both.
|
||||
*/
|
||||
public void onMessageSendSuccess() {
|
||||
if (VDBG) Log.v(TAG, "onMessageSendSuccess: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message transmission fails - i.e. when no ACK is received.
|
||||
* The hardware will usually attempt to re-transmit several times - this
|
||||
* event is received after all retries are exhausted. There is a possibility
|
||||
* that message was received by the destination successfully but the ACK was
|
||||
* lost. It is dummy method (empty implementation printing out a log
|
||||
* message). Override to implement your custom response.
|
||||
* <p>
|
||||
* Note that either this callback or
|
||||
* {@link WifiNanSessionListener#onMessageSendSuccess()} will be received -
|
||||
* never both
|
||||
*
|
||||
* @param reason The failure reason using {@code NanSessionListener.FAIL_*}
|
||||
* codes.
|
||||
*/
|
||||
public void onMessageSendFail(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onMessageSendFail: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message is received from a discovery session peer. It is
|
||||
* dummy method (empty implementation printing out a log message). Override
|
||||
* to implement your custom response.
|
||||
*
|
||||
* @param peerId The ID of the peer sending the message.
|
||||
* @param message A byte array containing the message.
|
||||
* @param messageLength The length of the byte array containing the relevant
|
||||
* message bytes.
|
||||
*/
|
||||
public void onMessageReceived(int peerId, byte[] message, int messageLength) {
|
||||
if (VDBG) Log.v(TAG, "onMessageReceived: called in stub - override if interested");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public IWifiNanSessionListener callback = new IWifiNanSessionListener.Stub() {
|
||||
@Override
|
||||
public void onPublishFail(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onPublishFail: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_PUBLISH_FAIL);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPublishTerminated(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onPublishResponse: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_PUBLISH_TERMINATED);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribeFail(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onSubscribeFail: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_SUBSCRIBE_FAIL);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribeTerminated(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onSubscribeTerminated: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_SUBSCRIBE_TERMINATED);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMatch(int peerId, byte[] serviceSpecificInfo,
|
||||
int serviceSpecificInfoLength, byte[] matchFilter, int matchFilterLength) {
|
||||
if (VDBG) Log.v(TAG, "onMatch: peerId=" + peerId);
|
||||
|
||||
Bundle data = new Bundle();
|
||||
data.putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId);
|
||||
data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, serviceSpecificInfo);
|
||||
data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2, matchFilter);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_MATCH);
|
||||
msg.arg1 = serviceSpecificInfoLength;
|
||||
msg.arg2 = matchFilterLength;
|
||||
msg.setData(data);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageSendSuccess() {
|
||||
if (VDBG) Log.v(TAG, "onMessageSendSuccess");
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_SUCCESS);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageSendFail(int reason) {
|
||||
if (VDBG) Log.v(TAG, "onMessageSendFail: reason=" + reason);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_FAIL);
|
||||
msg.arg1 = reason;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(int peerId, byte[] message, int messageLength) {
|
||||
if (VDBG) {
|
||||
Log.v(TAG, "onMessageReceived: peerId='" + peerId + "', messageLength="
|
||||
+ messageLength);
|
||||
}
|
||||
|
||||
Bundle data = new Bundle();
|
||||
data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, message);
|
||||
|
||||
Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_RECEIVED);
|
||||
msg.arg1 = messageLength;
|
||||
msg.arg2 = peerId;
|
||||
msg.setData(data);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
47
wifi/java/android/net/wifi/nan/WifiNanSubscribeSession.java
Normal file
47
wifi/java/android/net/wifi/nan/WifiNanSubscribeSession.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.wifi.nan;
|
||||
|
||||
/**
|
||||
* A representation of a NAN subscribe session. Created when
|
||||
* {@link WifiNanManager#subscribe(SubscribeData, SubscribeSettings, WifiNanSessionListener, int)}
|
||||
* is executed. The object can be used to stop and re-start (re-configure) the
|
||||
* subscribe session.
|
||||
*
|
||||
* @hide PROPOSED_NAN_API
|
||||
*/
|
||||
public class WifiNanSubscribeSession extends WifiNanSession {
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public WifiNanSubscribeSession(WifiNanManager manager, int sessionId) {
|
||||
super(manager, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart/re-configure the subscribe session. Note that the
|
||||
* {@link WifiNanSessionListener} is not replaced - the same listener used at
|
||||
* creation is still used.
|
||||
*
|
||||
* @param subscribeData The data ({@link SubscribeData}) to subscribe.
|
||||
* @param subscribeSettings The settings ({@link SubscribeSettings}) of the
|
||||
* subscribe session.
|
||||
*/
|
||||
public void subscribe(SubscribeData subscribeData, SubscribeSettings subscribeSettings) {
|
||||
mManager.subscribe(mSessionId, subscribeData, subscribeSettings);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user