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
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 450f816..cebcc47 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -356,6 +356,21 @@
         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);
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 50f624a..aa3554c 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -57,9 +57,21 @@
         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 @@
 
                 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;
             }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index 14246b4..e35d360 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -33,9 +33,6 @@
     /** The network name */
     private String mNetworkName;
 
-    /** The network bssid */
-    private String mNetworkBssid;
-
     /** Group owner */
     private WifiP2pDevice mOwner;
 
@@ -45,27 +42,12 @@
     /** 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 @@
      *  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 @@
                     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 @@
                     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 @@
         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 @@
     }
 
     /** 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 @@
         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;
             }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 0bdd269..11de9c4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -212,8 +212,8 @@
     /**
      * 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 @@
     /**
      * 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 @@
     /**
      * 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 @@
     /**
      * 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,7 +279,16 @@
      * {@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
+     * <p> This indicates that the operation failed due to an internal error
+     */
+    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 operation failed because p2p is unsupported on the
      * device
      */
     public static final int P2P_UNSUPPORTED     = 1;
@@ -289,21 +298,10 @@
      * {@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 the framework is busy and
+     * unable to service the request
      */
-    public static final int P2P_DISABLED        = 2;
-
-    /**
-     * 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
-     */
-    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 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
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index f67680d..333160f 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -129,6 +129,12 @@
     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 @@
                     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 @@
                 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 @@
             if (DBG) logd(getName());
             sendP2pStateChangedBroadcast(true);
             mNetworkInfo.setIsAvailable(true);
-            //Start listening for new connections
-            WifiNative.p2pListen();
             initializeP2pSettings();
         }
 
@@ -611,12 +624,14 @@
                     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 @@
                 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 @@
     }
 
     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 @@
                     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 @@
                         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 @@
                         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 @@
                     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 @@
                     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 @@
                         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 @@
         }
     }
 
+    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 @@
         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