Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4be4d31f authored by Irfan Sheriff's avatar Irfan Sheriff
Browse files

Fix p2p API interface to framework

- Update the WifiP2pGroup class
- Add reason code response for all failures
- Fix display of self in peer list
- Retain p2p group when explicitly created by API and fix join behavior

Bug: 5247957
Change-Id: Ibd9b163887db1c8a9dd8213253fda20c436a49e3
parent 9cc2718a
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -356,6 +356,21 @@ public class WifiNative {
        return null;
    }

    public static String p2pGetDeviceAddress() {
        String status = statusCommand();
        if (status == null) return "";

        String[] tokens = status.split("\n");
        for (String token : tokens) {
            if (token.startsWith("p2p_device_address=")) {
                String[] nameValue = token.split("=");
                if (nameValue.length != 2) break;
                return nameValue[1];
            }
        }
        return "";
    }

    public static String p2pPeer(String deviceAddress) {
        return doStringCommand("P2P_PEER " + deviceAddress);
    }
+15 −3
Original line number Diff line number Diff line
@@ -57,9 +57,21 @@ public class WifiP2pDeviceList implements Parcelable {
        return true;
    }

    public void add(WifiP2pDevice device) {
    public void update(WifiP2pDevice device) {
        if (device == null) return;
        if (mDevices.contains(device)) return;
        for (WifiP2pDevice d : mDevices) {
            //Found, update fields that can change
            if (d.equals(device)) {
                d.deviceName = device.deviceName;
                d.primaryDeviceType = device.primaryDeviceType;
                d.secondaryDeviceType = device.secondaryDeviceType;
                d.wpsConfigMethodsSupported = device.wpsConfigMethodsSupported;
                d.deviceCapability = device.deviceCapability;
                d.groupCapability = device.groupCapability;
                return;
            }
        }
        //Not found, add a new one
        mDevices.add(device);
    }

@@ -101,7 +113,7 @@ public class WifiP2pDeviceList implements Parcelable {

                int deviceCount = in.readInt();
                for (int i = 0; i < deviceCount; i++) {
                    deviceList.add((WifiP2pDevice)in.readParcelable(null));
                    deviceList.update((WifiP2pDevice)in.readParcelable(null));
                }
                return deviceList;
            }
+80 −42
Original line number Diff line number Diff line
@@ -33,9 +33,6 @@ public class WifiP2pGroup implements Parcelable {
    /** The network name */
    private String mNetworkName;

    /** The network bssid */
    private String mNetworkBssid;

    /** Group owner */
    private WifiP2pDevice mOwner;

@@ -45,27 +42,12 @@ public class WifiP2pGroup implements Parcelable {
    /** Group clients */
    private List<WifiP2pDevice> mClients = new ArrayList<WifiP2pDevice>();

    private int mChannel;

    /**
     * The network passphrase
     * <p/>
     * The passphrase used for WPA2-PSK
     */
    /** The passphrase used for WPA2-PSK */
    private String mPassphrase;

    /**
     * TODO: fix
     * Sometimes supplicant sends a psk
     */
    private String mPsk;

    /** Indicates that the group is persistent */
    private boolean mIsPersistent;

    private String mInterface;

    public WifiP2pGroup() {
    WifiP2pGroup() {
    }

    /**
@@ -81,6 +63,7 @@ public class WifiP2pGroup implements Parcelable {
     *  bssid=fa:7b:7a:42:82:13 unknown-network
     *
     *  Note: The events formats can be looked up in the wpa_supplicant code
     *  @hide
     */
    public WifiP2pGroup(String supplicantEvent) throws IllegalArgumentException {

@@ -103,20 +86,6 @@ public class WifiP2pGroup implements Parcelable {
                    continue;
                }

                if (nameValue[0].equals("freq")) {
                    try {
                        mChannel = Integer.parseInt(nameValue[1]);
                    } catch (NumberFormatException e) {
                        mChannel = 0; //invalid
                    }
                    continue;
                }

                if (nameValue[0].equals("psk")) {
                    mPsk = nameValue[1];
                    continue;
                }

                if (nameValue[0].equals("passphrase")) {
                    mPassphrase = nameValue[1];
                    continue;
@@ -135,28 +104,51 @@ public class WifiP2pGroup implements Parcelable {
                    mOwner = new WifiP2pDevice(nameValue[1]);
                    continue;
                }

                if (nameValue[0].equals("bssid")) {
                    mNetworkBssid = nameValue[1];
                }
            }
        } else {
            throw new IllegalArgumentException("Malformed supplicant event");
        }
    }

    /** @hide */
    public void setNetworkName(String networkName) {
        mNetworkName = networkName;
    }

    /**
     * Get the network name (SSID) of the group. Legacy Wi-Fi clients will discover
     * the p2p group using the network name.
     */
    public String getNetworkName() {
        return mNetworkName;
    }

    /** @hide */
    public void setIsGroupOwner(boolean isGo) {
        mIsGroupOwner = isGo;
    }

    /** Check whether this device is the group owner of the created p2p group */
    public boolean isGroupOwner() {
        return mIsGroupOwner;
    }

    /** @hide */
    public void setOwner(WifiP2pDevice device) {
        mOwner = device;
    }

    /** Get the details of the group owner as a {@link WifiP2pDevice} object */
    public WifiP2pDevice getOwner() {
        return mOwner;
    }

    /** @hide */
    public void addClient(String address) {
        addClient(new WifiP2pDevice(address));
    }

    /** @hide */
    public void addClient(WifiP2pDevice device) {
        for (WifiP2pDevice client : mClients) {
            if (client.equals(device)) return;
@@ -164,31 +156,60 @@ public class WifiP2pGroup implements Parcelable {
        mClients.add(device);
    }

    /** @hide */
    public boolean removeClient(String address) {
        return mClients.remove(new WifiP2pDevice(address));
    }

    /** @hide */
    public boolean removeClient(WifiP2pDevice device) {
        return mClients.remove(device);
    }

    /** @hide */
    public boolean isClientListEmpty() {
        return mClients.size() == 0;
    }

    /** Get the list of clients currently part of the p2p group */
    public Collection<WifiP2pDevice> getClientList() {
        return Collections.unmodifiableCollection(mClients);
    }

    /** @hide */
    public void setPassphrase(String passphrase) {
        mPassphrase = passphrase;
    }

    /**
     * Get the passphrase of the group. This function will return a valid passphrase only
     * at the group owner. Legacy Wi-Fi clients will need this passphrase alongside
     * network name obtained from {@link #getNetworkName()} to join the group
     */
    public String getPassphrase() {
        return mPassphrase;
    }

    /** @hide */
    public void setInterface(String intf) {
        mInterface = intf;
    }

    /** Get the interface name on which the group is created */
    public String getInterface() {
        return mInterface;
    }

    // TODO: implement
    /** @hide */
    public String toString() {
        StringBuffer sbuf = new StringBuffer();
        //sbuf.append("SSID: ").append(SSID);
        //sbuf.append("\n passphrase: ").append(passphrase);
        sbuf.append("network: ").append(mNetworkName);
        sbuf.append("\n isGO: ").append(mIsGroupOwner);
        sbuf.append("\n GO: ").append(mOwner);
        for (WifiP2pDevice client : mClients) {
            sbuf.append("\n Client: ").append(client);
        }
        sbuf.append("\n interface: ").append(mInterface);
        return sbuf.toString();
    }

@@ -205,8 +226,16 @@ public class WifiP2pGroup implements Parcelable {
    }

    /** Implement the Parcelable interface {@hide} */
    // STOPSHIP: implement
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mNetworkName);
        dest.writeParcelable(mOwner, flags);
        dest.writeByte(mIsGroupOwner ? (byte) 1: (byte) 0);
        dest.writeInt(mClients.size());
        for (WifiP2pDevice client : mClients) {
            dest.writeParcelable(client, flags);
        }
        dest.writeString(mPassphrase);
        dest.writeString(mInterface);
    }

    /** Implement the Parcelable interface {@hide} */
@@ -214,6 +243,15 @@ public class WifiP2pGroup implements Parcelable {
        new Creator<WifiP2pGroup>() {
            public WifiP2pGroup createFromParcel(Parcel in) {
                WifiP2pGroup group = new WifiP2pGroup();
                group.setNetworkName(in.readString());
                group.setOwner((WifiP2pDevice)in.readParcelable(null));
                group.setIsGroupOwner(in.readByte() == (byte)1);
                int clientCount = in.readInt();
                for (int i=0; i<clientCount; i++) {
                    group.addClient((WifiP2pDevice) in.readParcelable(null));
                }
                group.setPassphrase(in.readString());
                group.setInterface(in.readString());
                return group;
            }

+19 −21
Original line number Diff line number Diff line
@@ -212,8 +212,8 @@ public class WifiP2pManager {
    /**
     * Message {@link android.os.Message#what} value indicating that the {@link #discoverPeers}
     * operation failed.
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
     * or {@link #ALREADY_IN_EFFECT}
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #ERROR}
     * or {@link #BUSY}
     */
    public static final int DISCOVER_PEERS_FAILED                   = BASE + 8;
    /**
@@ -230,8 +230,8 @@ public class WifiP2pManager {
    /**
     * Message {@link android.os.Message#what} value indicating that the {@link #connect}
     * operation failed.
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
     * or {@link #ALREADY_IN_EFFECT}
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #ERROR}
     * or {@link #BUSY}
     */
    public static final int CONNECT_FAILED                          = BASE + 11;
    /**
@@ -248,8 +248,8 @@ public class WifiP2pManager {
    /**
     * Message {@link android.os.Message#what} value indicating that the {@link #createGroup}
     * operation failed.
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
     * or {@link #ALREADY_IN_EFFECT}
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #ERROR}
     * or {@link #BUSY}
     */
    public static final int CREATE_GROUP_FAILED                     = BASE + 14;
    /**
@@ -264,8 +264,8 @@ public class WifiP2pManager {
    /**
     * Message {@link android.os.Message#what} value indicating that the {@link #removeGroup}
     * operation failed.
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
     * or {@link #ALREADY_IN_EFFECT}
     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #ERROR}
     * or {@link #BUSY}
     */
    public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
    /**
@@ -279,31 +279,29 @@ public class WifiP2pManager {
     * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
     * and {@link #REMOVE_GROUP_FAILED}
     *
     * <p> This indicates that the reason for failure is because p2p is unsupported on the
     * device
     * <p> This indicates that the operation failed due to an internal error
     */
    public static final int P2P_UNSUPPORTED     = 1;
    public static final int ERROR               = 0;

    /**
     * Supported {@link android.os.Message#arg1} value on the following response messages:
     * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
     * and {@link #REMOVE_GROUP_FAILED}
     *
     * <p> This indicates that the reason for failure is because p2p is currently disabled
     * by the user
     * <p> This indicates that the operation failed because p2p is unsupported on the
     * device
     */
    public static final int P2P_DISABLED        = 2;
    public static final int P2P_UNSUPPORTED     = 1;

    /**
     * Supported {@link android.os.Message#arg1} value on the following response messages:
     * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
     * and {@link #REMOVE_GROUP_FAILED}
     *
     * <p> This indicates that the reason for failure is because the operation is already in
     * effect
     * <p> This indicates that the operation failed because the framework is busy and
     * unable to service the request
     */
    public static final int ALREADY_IN_EFFECT   = 3;

    public static final int BUSY                = 2;

    /** @hide */
    public static final int REQUEST_PEERS                           = BASE + 19;
@@ -342,11 +340,11 @@ public class WifiP2pManager {
    public static final int RESPONSE_GROUP_INFO                     = BASE + 24;

    /** @hide */
    public static final int WPS_PBC                                 = BASE + 23;
    public static final int WPS_PBC                                 = BASE + 25;
    /** @hide */
    public static final int WPS_PIN                                 = BASE + 24;
    public static final int WPS_PIN                                 = BASE + 26;
    /** @hide */
    public static final int WPS_PIN_AVAILABLE                       = BASE + 25;
    public static final int WPS_PIN_AVAILABLE                       = BASE + 27;

    /**
     * Create a new WifiP2pManager instance. Applications use
+67 −19
Original line number Diff line number Diff line
@@ -129,6 +129,12 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
    private final boolean mP2pSupported;
    private final String mDeviceType;
    private String mDeviceName;
    private String mDeviceAddress;

    /* When a group has been explicitly created by an app, we persist the group
     * even after all clients have been disconnected until an explicit remove
     * is invoked */
    private boolean mPersistGroup;

    private NetworkInfo mNetworkInfo;

@@ -315,22 +321,28 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                    deferMessage(message);
                    break;
                case WifiP2pManager.ENABLE_P2P:
                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                case WifiP2pManager.DISABLE_P2P:
                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                case WifiP2pManager.DISCOVER_PEERS:
                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                case WifiP2pManager.CONNECT:
                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                case WifiP2pManager.CREATE_GROUP:
                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                case WifiP2pManager.REMOVE_GROUP:
                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                case WifiP2pManager.REQUEST_PEERS:
                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
@@ -338,6 +350,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                case WifiP2pManager.REQUEST_CONNECTION_INFO:
                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
                    break;
                case WifiP2pManager.REQUEST_GROUP_INFO:
                    replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
                    break;
                // Ignore
                case WIFI_DISABLE_USER_ACCEPT:
                case GROUP_NEGOTIATION_TIMED_OUT:
@@ -589,8 +604,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
            if (DBG) logd(getName());
            sendP2pStateChangedBroadcast(true);
            mNetworkInfo.setIsAvailable(true);
            //Start listening for new connections
            WifiNative.p2pListen();
            initializeP2pSettings();
        }

@@ -611,12 +624,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                    if (WifiNative.p2pFind(timeout)) {
                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
                    } else {
                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                                WifiP2pManager.ERROR);
                    }
                    break;
                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
                    mPeers.add(device);
                    if (mDeviceAddress.equals(device.deviceAddress)) break;
                    mPeers.update(device);
                    sendP2pPeersChangedBroadcast();
                    break;
                case WifiMonitor.P2P_DEVICE_LOST_EVENT:
@@ -626,13 +641,15 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                case WifiP2pManager.CONNECT:
                    if (DBG) logd(getName() + " sending connect");
                    mSavedConnectConfig = (WifiP2pConfig) message.obj;
                    mPersistGroup = false;
                    int netId = configuredNetworkId(mSavedConnectConfig.deviceAddress);
                    if (netId >= 0) {
                        //TODO: if failure, remove config and do a regular p2pConnect()
                        WifiNative.p2pReinvoke(netId, mSavedConnectConfig.deviceAddress);
                    } else {
                        //TODO: Check if device is a GO and "join"
                        String pin = WifiNative.p2pConnect(mSavedConnectConfig, false);
                        boolean join = false;
                        if (isGroupOwner(mSavedConnectConfig.deviceAddress)) join = true;
                        String pin = WifiNative.p2pConnect(mSavedConnectConfig, join);
                        try {
                            Integer.parseInt(pin);
                            notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
@@ -682,8 +699,11 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
    }

    class InactiveState extends State {
        @Override public void enter() {
        @Override
        public void enter() {
            if (DBG) logd(getName());
            //Start listening every time we get inactive
            WifiNative.p2pListen();
        }

        @Override
@@ -695,10 +715,12 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                    notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig);
                    break;
                case WifiP2pManager.CREATE_GROUP:
                    mPersistGroup = true;
                    if (WifiNative.p2pGroupAdd()) {
                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
                    } else {
                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
                                WifiP2pManager.ERROR);
                    }
                    transitionTo(mGroupNegotiationState);
                    break;
@@ -748,6 +770,11 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                        transitionTo(mInactiveState);
                    }
                    break;
                case WifiP2pManager.DISCOVER_PEERS:
                    /* Discovery will break negotiation */
                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                            WifiP2pManager.BUSY);
                    break;
                default:
                    return NOT_HANDLED;
            }
@@ -792,13 +819,17 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                        updateDeviceStatus(deviceAddress, Status.AVAILABLE);
                        if (mGroup.removeClient(deviceAddress)) {
                            if (DBG) logd("Removed client " + deviceAddress);
                            sendP2pPeersChangedBroadcast();
                            if (!mPersistGroup && mGroup.isClientListEmpty()) {
                                Slog.d(TAG, "Client list empty, remove non-persistent p2p group");
                                WifiNative.p2pGroupRemove(mGroup.getInterface());
                            }
                        } else {
                            if (DBG) logd("Failed to remove client " + deviceAddress);
                            for (WifiP2pDevice c : mGroup.getClientList()) {
                                if (DBG) logd("client " + c.deviceAddress);
                            }
                        }
                        sendP2pPeersChangedBroadcast();
                        if (DBG) loge(getName() + " ap sta disconnected");
                    } else {
                        loge("Disconnect on unknown device address : " + interfaceAddress);
@@ -820,7 +851,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                    if (WifiNative.p2pGroupRemove(mGroup.getInterface())) {
                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
                    } else {
                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
                                WifiP2pManager.ERROR);
                    }
                    break;
                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
@@ -852,8 +884,11 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                    if (device.equals(mGroup.getOwner())) {
                        logd("Lost the group owner, killing p2p connection");
                        WifiNative.p2pGroupRemove(mGroup.getInterface());
                    } else {
                        mGroup.removeClient(device);
                    } else if (mGroup.removeClient(device)) {
                        if (!mPersistGroup && mGroup.isClientListEmpty()) {
                            Slog.d(TAG, "Client list empty, removing a non-persistent p2p group");
                            WifiNative.p2pGroupRemove(mGroup.getInterface());
                        }
                    }
                    return NOT_HANDLED; // Do the regular device lost handling
                case WifiP2pManager.DISABLE_P2P:
@@ -868,7 +903,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
                        sendP2pPeersChangedBroadcast();
                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
                    } else {
                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
                                WifiP2pManager.ERROR);
                    }
                    // TODO: figure out updating the status to declined when invitation is rejected
                    break;
@@ -1118,6 +1154,15 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
        }
    }

    private boolean isGroupOwner(String deviceAddress) {
        for (WifiP2pDevice d : mPeers.getDeviceList()) {
            if (d.deviceAddress.equals(deviceAddress)) {
                return d.isGroupOwner();
            }
        }
        return false;
    }

    //TODO: implement when wpa_supplicant is fixed
    private int configuredNetworkId(String deviceAddress) {
        return -1;
@@ -1148,6 +1193,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
        WifiNative.setPersistentReconnect(true);
        WifiNative.setDeviceName(mDeviceName);
        WifiNative.setDeviceType(mDeviceType);

        mDeviceAddress = WifiNative.p2pGetDeviceAddress();
        if (DBG) Slog.d(TAG, "DeviceAddress: " + mDeviceAddress);
    }

    //State machine initiated requests can have replyTo set to null indicating