121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff/*
221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * Copyright (C) 2012 The Android Open Source Project
321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff *
421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License");
521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * you may not use this file except in compliance with the License.
621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * You may obtain a copy of the License at
721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff *
821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff *      http://www.apache.org/licenses/LICENSE-2.0
921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff *
1021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * Unless required by applicable law or agreed to in writing, software
1121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS,
1221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * See the License for the specific language governing permissions and
1421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * limitations under the License.
1521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff */
1621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
1721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffpackage android.net.wifi.p2p.nsd;
1821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
1921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport android.net.wifi.p2p.WifiP2pDevice;
2021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport android.os.Parcel;
2121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport android.os.Parcelable;
2221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
2321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport java.io.ByteArrayInputStream;
2421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport java.io.DataInputStream;
2521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport java.io.IOException;
2621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport java.util.ArrayList;
2721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport java.util.Arrays;
2821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffimport java.util.List;
2921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
3021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff/**
3121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * The class for a response of service discovery.
3221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff *
3321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff * @hide
3421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff */
3521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriffpublic class WifiP2pServiceResponse implements Parcelable {
3621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
3721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    private static int MAX_BUF_SIZE = 1024;
3821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
3921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
4021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Service type. It's defined in table63 in Wi-Fi Direct specification.
4121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
4221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    protected int mServiceType;
4321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
4421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
4521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Status code of service discovery response.
4621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * It's defined in table65 in Wi-Fi Direct specification.
4721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @see Status
4821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
4921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    protected int mStatus;
5021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
5121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
5221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Service transaction ID.
5321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * This is a nonzero value used to match the service request/response TLVs.
5421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
5521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    protected int mTransId;
5621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
5721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
5821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Source device.
5921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
6021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    protected WifiP2pDevice mDevice;
6121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
6221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
6321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Service discovery response data based on the requested on
6421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * the service protocol type. The protocol format depends on the service type.
6521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
6621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    protected byte[] mData;
6721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
6821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
6921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
7021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * The status code of service discovery response.
7121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Currently 4 status codes are defined and the status codes from  4 to 255
7221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * are reserved.
7321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
7421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * See Wi-Fi Direct specification for the detail.
7521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
7621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public static class Status {
7721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        /** success */
7821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        public static final int SUCCESS = 0;
7921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
8021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        /** the service protocol type is not available */
8121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        public static final int SERVICE_PROTOCOL_NOT_AVAILABLE = 1;
8221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
8321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        /** the requested information is not available */
8421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        public static final int REQUESTED_INFORMATION_NOT_AVAILABLE = 2;
8521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
8621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        /** bad request */
8721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        public static final int BAD_REQUEST = 3;
8821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
8921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        /** @hide */
9021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        public static String toString(int status) {
9121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            switch(status) {
9221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            case SUCCESS:
9321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return "SUCCESS";
9421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            case SERVICE_PROTOCOL_NOT_AVAILABLE:
9521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return "SERVICE_PROTOCOL_NOT_AVAILABLE";
9621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            case REQUESTED_INFORMATION_NOT_AVAILABLE:
9721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return "REQUESTED_INFORMATION_NOT_AVAILABLE";
9821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            case BAD_REQUEST:
9921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return "BAD_REQUEST";
10021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            default:
10121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return "UNKNOWN";
10221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            }
10321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
10421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
10521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        /** not used */
10621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        private Status() {}
10721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
10821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
10921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
11021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Hidden constructor. This is only used in framework.
11121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
11221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param serviceType service discovery type.
11321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param status status code.
11421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param transId transaction id.
11521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param device source device.
11621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param data query data.
11721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
11821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    protected WifiP2pServiceResponse(int serviceType, int status, int transId,
11921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            WifiP2pDevice device, byte[] data) {
12021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        mServiceType = serviceType;
12121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        mStatus = status;
12221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        mTransId = transId;
12321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        mDevice = device;
12421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        mData = data;
12521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
12621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
12721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
12821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Return the service type of service discovery response.
12921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
13021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return service discovery type.<br>
13121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * e.g) {@link WifiP2pServiceInfo#SERVICE_TYPE_BONJOUR}
13221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
13321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public int getServiceType() {
13421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return mServiceType;
13521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
13621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
13721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
13821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Return the status code of service discovery response.
13921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
14021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return status code.
14121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @see Status
14221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
14321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public int getStatus() {
14421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return mStatus;
14521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
14621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
14721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
14821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Return the transaction id of service discovery response.
14921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
15021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return transaction id.
15121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @hide
15221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
15321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public int getTransactionId() {
15421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return mTransId;
15521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
15621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
15721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
15821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Return response data.
15921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
16021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * <pre>Data format depends on service type
16121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
16221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return a query or response data.
16321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
16421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public byte[] getRawData() {
16521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return mData;
16621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
16721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
16821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
16921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Returns the source device of service discovery response.
17021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
17121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * <pre>This is valid only when service discovery response.
17221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
17321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return the source device of service discovery response.
17421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
17521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public WifiP2pDevice getSrcDevice() {
17621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return mDevice;
17721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
17821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
17921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /** @hide */
18021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public void setSrcDevice(WifiP2pDevice dev) {
18121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (dev == null) return;
18221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        this.mDevice = dev;
18321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
18421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
18521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
18621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
18721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Create the list of  WifiP2pServiceResponse instance from supplicant event.
18821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
18921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * <pre>The format is as follows.
19021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * P2P-SERV-DISC-RESP &lt;address&gt; &lt;update indicator&gt; &lt;response data&gt;
19121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * e.g) P2P-SERV-DISC-RESP 02:03:7f:11:62:da 1 0300000101
19221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
19321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param supplicantEvent wpa_supplicant event string.
19421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return if parse failed, return null
19521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @hide
19621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
19721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public static List<WifiP2pServiceResponse> newInstance(String supplicantEvent) {
19821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
19921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        List<WifiP2pServiceResponse> respList = new ArrayList<WifiP2pServiceResponse>();
20021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        String[] args = supplicantEvent.split(" ");
20121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (args.length != 4) {
20221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return null;
20321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
20421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        WifiP2pDevice dev = new WifiP2pDevice();
20521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        String srcAddr = args[1];
20621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        dev.deviceAddress = srcAddr;
20721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        //String updateIndicator = args[2];//not used.
20821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        byte[] bin = hexStr2Bin(args[3]);
20921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (bin == null) {
21021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return null;
21121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
21221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
21321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bin));
21421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        try {
21521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            while (dis.available() > 0) {
21621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                /*
21721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                 * Service discovery header is as follows.
21821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                 * ______________________________________________________________
21921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                 * |           Length(2byte)     | Type(1byte) | TransId(1byte)}|
22021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                 * ______________________________________________________________
22121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                 * | status(1byte)  |            vendor specific(variable)      |
22221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                 */
22321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                // The length equals to 3 plus the number of octets in the vendor
22421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                // specific content field. And this is little endian.
22521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int length = ((dis.readByte() & 0xff) +
22621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                        ((dis.readByte() & 0xff) << 8)) - 3;
22721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int type = dis.readUnsignedByte();
22821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                byte transId = dis.readByte();
22921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int status = dis.readUnsignedByte();
23021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (length < 0) {
23121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    return null;
23221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
23321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (length == 0) {
23421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    if (status == Status.SUCCESS) {
23521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                        respList.add(new WifiP2pServiceResponse(type, status,
23621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                            transId, dev, null));
23721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    }
23821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    continue;
23921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
24021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (length > MAX_BUF_SIZE) {
24121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    dis.skip(length);
24221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    continue;
24321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
24421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                byte[] data = new byte[length];
24521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                dis.readFully(data);
24621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
24721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                WifiP2pServiceResponse resp;
24821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (type ==  WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
2498bf825f48fde77cb2feb8720aac17093581bb085Irfan Sheriff                    resp = WifiP2pDnsSdServiceResponse.newInstance(status,
25021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                            transId, dev, data);
25121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
25221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    resp = WifiP2pUpnpServiceResponse.newInstance(status,
25321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                            transId, dev, data);
25421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                } else {
25521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    resp = new WifiP2pServiceResponse(type, status, transId, dev, data);
25621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
25721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (resp != null && resp.getStatus() == Status.SUCCESS) {
25821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    respList.add(resp);
25921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
26021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            }
26121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return respList;
26221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        } catch (IOException e) {
26321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            e.printStackTrace();
26421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
26521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
26621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (respList.size() > 0) {
26721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return respList;
26821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
26921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return null;
27021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
27121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
27221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /**
27321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * Converts hex string to byte array.
27421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     *
27521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @param hex hex string. if invalid, return null.
27621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     * @return binary data.
27721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff     */
27821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    private static byte[] hexStr2Bin(String hex) {
27921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        int sz = hex.length()/2;
28021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        byte[] b = new byte[hex.length()/2];
28121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
28221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        for (int i=0;i<sz;i++) {
28321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            try {
28421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                b[i] = (byte)Integer.parseInt(hex.substring(i*2, i*2+2), 16);
28521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            } catch (Exception e) {
28621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                e.printStackTrace();
28721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return null;
28821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            }
28921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
29021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return b;
29121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
29221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
29321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    @Override
29421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public String toString() {
29521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        StringBuffer sbuf = new StringBuffer();
29621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        sbuf.append("serviceType:").append(mServiceType);
29721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        sbuf.append(" status:").append(Status.toString(mStatus));
29821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        sbuf.append(" srcAddr:").append(mDevice.deviceAddress);
29921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        sbuf.append(" data:").append(mData);
30021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return sbuf.toString();
30121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
30221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
30321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    @Override
30421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public boolean equals(Object o) {
30521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (o == this) {
30621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return true;
30721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
30821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (!(o instanceof WifiP2pServiceResponse)) {
30921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return false;
31021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
31121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
31221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        WifiP2pServiceResponse req = (WifiP2pServiceResponse)o;
31321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
31421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return (req.mServiceType == mServiceType) &&
31521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            (req.mStatus == mStatus) &&
31621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                equals(req.mDevice.deviceAddress, mDevice.deviceAddress) &&
31721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                Arrays.equals(req.mData, mData);
31821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
31921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
32021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    private boolean equals(Object a, Object b) {
32121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (a == null && b == null) {
32221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return true;
32321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        } else if (a != null) {
32421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            return a.equals(b);
32521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
32621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return false;
32721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
32821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
32921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    @Override
33021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public int hashCode() {
33121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        int result = 17;
33221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        result = 31 * result + mServiceType;
33321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        result = 31 * result + mStatus;
33421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        result = 31 * result + mTransId;
33521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        result = 31 * result + (mDevice.deviceAddress == null ?
33621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                0 : mDevice.deviceAddress.hashCode());
33721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        result = 31 * result + (mData == null ? 0 : mData.hashCode());
33821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return result;
33921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
34021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
34121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
34221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public int describeContents() {
34321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        return 0;
34421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
34521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
34621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
34721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public void writeToParcel(Parcel dest, int flags) {
34821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        dest.writeInt(mServiceType);
34921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        dest.writeInt(mStatus);
35021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        dest.writeInt(mTransId);
35121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        dest.writeParcelable(mDevice, flags);
35221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        if (mData == null || mData.length == 0) {
35321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            dest.writeInt(0);
35421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        } else {
35521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            dest.writeInt(mData.length);
35621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            dest.writeByteArray(mData);
35721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        }
35821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    }
35921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
36021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
36121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff    public static final Creator<WifiP2pServiceResponse> CREATOR =
36221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        new Creator<WifiP2pServiceResponse>() {
36321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            public WifiP2pServiceResponse createFromParcel(Parcel in) {
36421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
36521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int type = in.readInt();
36621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int status = in.readInt();
36721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int transId = in.readInt();
36821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                WifiP2pDevice dev = (WifiP2pDevice)in.readParcelable(null);
36921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                int len = in.readInt();
37021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                byte[] data = null;
37121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (len > 0) {
37221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    data = new byte[len];
37321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    in.readByteArray(data);
37421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
37521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                if (type ==  WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
3768bf825f48fde77cb2feb8720aac17093581bb085Irfan Sheriff                    return WifiP2pDnsSdServiceResponse.newInstance(status,
37721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                            transId, dev, data);
37821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
37921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                    return WifiP2pUpnpServiceResponse.newInstance(status,
38021ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                            transId, dev, data);
38121ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                }
38221ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return new WifiP2pServiceResponse(type, status, transId, dev, data);
38321ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            }
38421ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff
38521ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            public WifiP2pServiceResponse[] newArray(int size) {
38621ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff                return new WifiP2pServiceResponse[size];
38721ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff            }
38821ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff        };
38921ba8153325e010224c6bc75a0acdc98b6ca82e8Irfan Sheriff}
390