android.net.wifi.p2p.nsd.WifiP2pServiceResponse Maven / Gradle / Ivy
/*
* Copyright (C) 2012 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.p2p.nsd;
import android.net.wifi.p2p.WifiP2pDevice;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* The class for a response of service discovery.
*
* @hide
*/
public class WifiP2pServiceResponse implements Parcelable {
private static int MAX_BUF_SIZE = 1024;
/**
* Service type. It's defined in table63 in Wi-Fi Direct specification.
*/
protected int mServiceType;
/**
* Status code of service discovery response.
* It's defined in table65 in Wi-Fi Direct specification.
* @see Status
*/
protected int mStatus;
/**
* Service transaction ID.
* This is a nonzero value used to match the service request/response TLVs.
*/
protected int mTransId;
/**
* Source device.
*/
protected WifiP2pDevice mDevice;
/**
* Service discovery response data based on the requested on
* the service protocol type. The protocol format depends on the service type.
*/
protected byte[] mData;
/**
* The status code of service discovery response.
* Currently 4 status codes are defined and the status codes from 4 to 255
* are reserved.
*
* See Wi-Fi Direct specification for the detail.
*/
public static class Status {
/** success */
public static final int SUCCESS = 0;
/** the service protocol type is not available */
public static final int SERVICE_PROTOCOL_NOT_AVAILABLE = 1;
/** the requested information is not available */
public static final int REQUESTED_INFORMATION_NOT_AVAILABLE = 2;
/** bad request */
public static final int BAD_REQUEST = 3;
/** @hide */
public static String toString(int status) {
switch(status) {
case SUCCESS:
return "SUCCESS";
case SERVICE_PROTOCOL_NOT_AVAILABLE:
return "SERVICE_PROTOCOL_NOT_AVAILABLE";
case REQUESTED_INFORMATION_NOT_AVAILABLE:
return "REQUESTED_INFORMATION_NOT_AVAILABLE";
case BAD_REQUEST:
return "BAD_REQUEST";
default:
return "UNKNOWN";
}
}
/** not used */
private Status() {}
}
/**
* Hidden constructor. This is only used in framework.
*
* @param serviceType service discovery type.
* @param status status code.
* @param transId transaction id.
* @param device source device.
* @param data query data.
*/
protected WifiP2pServiceResponse(int serviceType, int status, int transId,
WifiP2pDevice device, byte[] data) {
mServiceType = serviceType;
mStatus = status;
mTransId = transId;
mDevice = device;
mData = data;
}
/**
* Return the service type of service discovery response.
*
* @return service discovery type.
* e.g) {@link WifiP2pServiceInfo#SERVICE_TYPE_BONJOUR}
*/
public int getServiceType() {
return mServiceType;
}
/**
* Return the status code of service discovery response.
*
* @return status code.
* @see Status
*/
public int getStatus() {
return mStatus;
}
/**
* Return the transaction id of service discovery response.
*
* @return transaction id.
* @hide
*/
public int getTransactionId() {
return mTransId;
}
/**
* Return response data.
*
* Data format depends on service type
*
* @return a query or response data.
*/
public byte[] getRawData() {
return mData;
}
/**
* Returns the source device of service discovery response.
*
* This is valid only when service discovery response.
*
* @return the source device of service discovery response.
*/
public WifiP2pDevice getSrcDevice() {
return mDevice;
}
/** @hide */
public void setSrcDevice(WifiP2pDevice dev) {
if (dev == null) return;
this.mDevice = dev;
}
/**
* Create the list of WifiP2pServiceResponse instance from supplicant event.
*
* The format is as follows.
* P2P-SERV-DISC-RESP <address> <update indicator> <response data>
* e.g) P2P-SERV-DISC-RESP 02:03:7f:11:62:da 1 0300000101
*
* @param supplicantEvent wpa_supplicant event string.
* @return if parse failed, return null
* @hide
*/
public static List newInstance(String supplicantEvent) {
List respList = new ArrayList();
String[] args = supplicantEvent.split(" ");
if (args.length != 4) {
return null;
}
WifiP2pDevice dev = new WifiP2pDevice();
String srcAddr = args[1];
dev.deviceAddress = srcAddr;
//String updateIndicator = args[2];//not used.
byte[] bin = hexStr2Bin(args[3]);
if (bin == null) {
return null;
}
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bin));
try {
while (dis.available() > 0) {
/*
* Service discovery header is as follows.
* ______________________________________________________________
* | Length(2byte) | Type(1byte) | TransId(1byte)}|
* ______________________________________________________________
* | status(1byte) | vendor specific(variable) |
*/
// The length equals to 3 plus the number of octets in the vendor
// specific content field. And this is little endian.
int length = (dis.readUnsignedByte() +
(dis.readUnsignedByte() << 8)) - 3;
int type = dis.readUnsignedByte();
int transId = dis.readUnsignedByte();
int status = dis.readUnsignedByte();
if (length < 0) {
return null;
}
if (length == 0) {
if (status == Status.SUCCESS) {
respList.add(new WifiP2pServiceResponse(type, status,
transId, dev, null));
}
continue;
}
if (length > MAX_BUF_SIZE) {
dis.skip(length);
continue;
}
byte[] data = new byte[length];
dis.readFully(data);
WifiP2pServiceResponse resp;
if (type == WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
resp = WifiP2pDnsSdServiceResponse.newInstance(status,
transId, dev, data);
} else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
resp = WifiP2pUpnpServiceResponse.newInstance(status,
transId, dev, data);
} else {
resp = new WifiP2pServiceResponse(type, status, transId, dev, data);
}
if (resp != null && resp.getStatus() == Status.SUCCESS) {
respList.add(resp);
}
}
return respList;
} catch (IOException e) {
e.printStackTrace();
}
if (respList.size() > 0) {
return respList;
}
return null;
}
/**
* Converts hex string to byte array.
*
* @param hex hex string. if invalid, return null.
* @return binary data.
*/
private static byte[] hexStr2Bin(String hex) {
int sz = hex.length()/2;
byte[] b = new byte[hex.length()/2];
for (int i=0;i CREATOR =
new Creator() {
public WifiP2pServiceResponse createFromParcel(Parcel in) {
int type = in.readInt();
int status = in.readInt();
int transId = in.readInt();
WifiP2pDevice dev = (WifiP2pDevice)in.readParcelable(null);
int len = in.readInt();
byte[] data = null;
if (len > 0) {
data = new byte[len];
in.readByteArray(data);
}
if (type == WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
return WifiP2pDnsSdServiceResponse.newInstance(status,
transId, dev, data);
} else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
return WifiP2pUpnpServiceResponse.newInstance(status,
transId, dev, data);
}
return new WifiP2pServiceResponse(type, status, transId, dev, data);
}
public WifiP2pServiceResponse[] newArray(int size) {
return new WifiP2pServiceResponse[size];
}
};
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy