Merge "Update RemoteControlDisplay interface for playback position" into jb-mr2-dev
diff --git a/jni/com_android_bluetooth_avrcp.cpp b/jni/com_android_bluetooth_avrcp.cpp
index ee7083e..125ac4b 100644
--- a/jni/com_android_bluetooth_avrcp.cpp
+++ b/jni/com_android_bluetooth_avrcp.cpp
@@ -226,14 +226,15 @@
             env->DeleteLocalRef(text);
             break;
         }
+
+        pAttrs[i].attr_id = attr[i];
         if (strlen(textStr) >= BTRC_MAX_ATTR_STR_LEN) {
             ALOGE("get_element_attr_rsp: string length exceed maximum");
-            env->ReleaseStringUTFChars(text, textStr);
-            env->DeleteLocalRef(text);
-            break;
+            strncpy((char *)pAttrs[i].text, textStr, BTRC_MAX_ATTR_STR_LEN-1);
+            pAttrs[i].text[BTRC_MAX_ATTR_STR_LEN-1] = 0;
+        } else {
+            strcpy((char *)pAttrs[i].text, textStr);
         }
-        pAttrs[i].attr_id = attr[i];
-        strcpy((char *)pAttrs[i].text, textStr);
         env->ReleaseStringUTFChars(text, textStr);
         env->DeleteLocalRef(text);
     }
diff --git a/src/com/android/bluetooth/pan/PanService.java b/src/com/android/bluetooth/pan/PanService.java
index c0ada7c..22f4d83 100755
--- a/src/com/android/bluetooth/pan/PanService.java
+++ b/src/com/android/bluetooth/pan/PanService.java
@@ -30,17 +30,21 @@
 import android.net.ConnectivityManager;
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkStateTracker;
 import android.net.NetworkUtils;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.Message;
+import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
 import android.util.Log;
 import com.android.bluetooth.btservice.ProfileService;
 import com.android.bluetooth.Utils;
+import com.android.internal.util.AsyncChannel;
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -73,6 +77,8 @@
     private static final int MESSAGE_CONNECT_STATE_CHANGED = 11;
     private boolean mTetherOn = false;
 
+    AsyncChannel mTetherAc;
+
 
     static {
         classInitNative();
@@ -97,11 +103,20 @@
         }
         initializeNative();
         mNativeAvailable=true;
+
+        ConnectivityManager cm = (ConnectivityManager) getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        cm.supplyMessenger(ConnectivityManager.TYPE_BLUETOOTH, new Messenger(mHandler));
+
         return true;
     }
 
     protected boolean stop() {
         mHandler.removeCallbacksAndMessages(null);
+        if (mTetherAc != null) {
+            mTetherAc.disconnect();
+            mTetherAc = null;
+        }
         return true;
     }
 
@@ -113,8 +128,8 @@
         if(mPanDevices != null) {
             List<BluetoothDevice> DevList = getConnectedDevices();
             for(BluetoothDevice dev : DevList) {
-               handlePanDeviceStateChange(dev, mPanIfName, BluetoothProfile.STATE_DISCONNECTED,
-                                                   BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
+                handlePanDeviceStateChange(dev, mPanIfName, BluetoothProfile.STATE_DISCONNECTED,
+                        BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
             }
             mPanDevices.clear();
         }
@@ -131,11 +146,13 @@
                 case MESSAGE_CONNECT:
                 {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
-                    if (!connectPanNative(Utils.getByteAddress(device), BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE)) {
+                    if (!connectPanNative(Utils.getByteAddress(device),
+                            BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE)) {
                         handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_CONNECTING,
-                                                   BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
-                        handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_DISCONNECTED,
-                                                   BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
+                                BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
+                        handlePanDeviceStateChange(device, null,
+                                BluetoothProfile.STATE_DISCONNECTED, BluetoothPan.LOCAL_PANU_ROLE,
+                                BluetoothPan.REMOTE_NAP_ROLE);
                         break;
                     }
                 }
@@ -144,10 +161,12 @@
                 {
                     BluetoothDevice device = (BluetoothDevice) msg.obj;
                     if (!disconnectPanNative(Utils.getByteAddress(device)) ) {
-                        handlePanDeviceStateChange(device, mPanIfName, BluetoothProfile.STATE_DISCONNECTING,
-                                                   BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
-                        handlePanDeviceStateChange(device, mPanIfName, BluetoothProfile.STATE_DISCONNECTED,
-                                                   BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
+                        handlePanDeviceStateChange(device, mPanIfName,
+                                BluetoothProfile.STATE_DISCONNECTING, BluetoothPan.LOCAL_PANU_ROLE,
+                                BluetoothPan.REMOTE_NAP_ROLE);
+                        handlePanDeviceStateChange(device, mPanIfName,
+                                BluetoothProfile.STATE_DISCONNECTED, BluetoothPan.LOCAL_PANU_ROLE,
+                                BluetoothPan.REMOTE_NAP_ROLE);
                         break;
                     }
                 }
@@ -157,9 +176,33 @@
                     ConnectState cs = (ConnectState)msg.obj;
                     BluetoothDevice device = getDevice(cs.addr);
                     // TBD get iface from the msg
-                    if (DBG) log("MESSAGE_CONNECT_STATE_CHANGED: " + device + " state: " + cs.state);
-                    handlePanDeviceStateChange(device, mPanIfName /* iface */, convertHalState(cs.state),
-                                               cs.local_role,  cs.remote_role);
+                    if (DBG) {
+                        log("MESSAGE_CONNECT_STATE_CHANGED: " + device + " state: " + cs.state);
+                    }
+                    handlePanDeviceStateChange(device, mPanIfName /* iface */,
+                            convertHalState(cs.state), cs.local_role,  cs.remote_role);
+                }
+                break;
+                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
+                {
+                    if (mTetherAc != null) {
+                        mTetherAc.replyToMessage(msg,
+                                AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+                                AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
+                    } else {
+                        mTetherAc = new AsyncChannel();
+                        mTetherAc.connected(null, this, msg.replyTo);
+                        mTetherAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+                                AsyncChannel.STATUS_SUCCESSFUL);
+                    }
+                }
+                break;
+                case AsyncChannel.CMD_CHANNEL_DISCONNECT:
+                {
+                    if (mTetherAc != null) {
+                        mTetherAc.disconnect();
+                        mTetherAc = null;
+                    }
                 }
                 break;
             }
@@ -169,7 +212,8 @@
     /**
      * Handlers for incoming service calls
      */
-    private static class BluetoothPanBinder extends IBluetoothPan.Stub implements IProfileServiceBinder {
+    private static class BluetoothPanBinder extends IBluetoothPan.Stub
+            implements IProfileServiceBinder {
         private PanService mService;
         public BluetoothPanBinder(PanService svc) {
             mService = svc;
@@ -328,8 +372,12 @@
         int local_role;
         int remote_role;
     };
-    private void onConnectStateChanged(byte[] address, int state, int error, int local_role, int remote_role) {
-        if (DBG) log("onConnectStateChanged: " + state + ", local role:" + local_role + ", remote_role: " + remote_role);
+    private void onConnectStateChanged(byte[] address, int state, int error, int local_role,
+            int remote_role) {
+        if (DBG) {
+            log("onConnectStateChanged: " + state + ", local role:" + local_role +
+                    ", remote_role: " + remote_role);
+        }
         Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_STATE_CHANGED);
         msg.obj = new ConnectState(address, state, error, local_role, remote_role);
         mHandler.sendMessage(msg);
@@ -359,8 +407,11 @@
 
     void handlePanDeviceStateChange(BluetoothDevice device,
                                     String iface, int state, int local_role, int remote_role) {
-        if(DBG) Log.d(TAG, "handlePanDeviceStateChange: device: " + device + ", iface: " + iface +
-                    ", state: " + state + ", local_role:" + local_role + ", remote_role:" + remote_role);
+        if(DBG) {
+            Log.d(TAG, "handlePanDeviceStateChange: device: " + device + ", iface: " + iface +
+                    ", state: " + state + ", local_role:" + local_role + ", remote_role:" +
+                    remote_role);
+        }
         int prevState;
         String ifaceAddr = null;
         BluetoothPanDevice panDevice = mPanDevices.get(device);
@@ -392,31 +443,18 @@
             }
         } else {
             // PANU Role = reverse Tether
-            Log.d(TAG, "handlePanDeviceStateChange LOCAL_PANU_ROLE:REMOTE_NAP_ROLE");
+            Log.d(TAG, "handlePanDeviceStateChange LOCAL_PANU_ROLE:REMOTE_NAP_ROLE state = " +
+                    state + ", prevState = " + prevState);
             if (state == BluetoothProfile.STATE_CONNECTED) {
-                if(DBG) Log.d(TAG, "handlePanDeviceStateChange: panu STATE_CONNECTED, startReverseTether");
-                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-                Log.d(TAG, "call INetworkManagementService.startReverseTethering()");
-                try {
-                    service.startReverseTethering(iface);
-                } catch (Exception e) {
-                    Log.e(TAG, "Cannot start reverse tethering: " + e);
-                    return;
-                }
-            } else if (state == BluetoothProfile.STATE_DISCONNECTED &&
-                  (prevState == BluetoothProfile.STATE_CONNECTED ||
-                  prevState == BluetoothProfile.STATE_DISCONNECTING)) {
-                if(DBG) Log.d(TAG, "handlePanDeviceStateChange: stopReverseTether, panDevice.mIface: "
-                                    + panDevice.mIface);
-                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-                try {
-                    service.stopReverseTethering();
-                } catch(Exception e) {
-                    Log.e(TAG, "Cannot stop reverse tethering: " + e);
-                    return;
-                }
+                LinkProperties lp = new LinkProperties();
+                lp.setInterfaceName(iface);
+                mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_CONNECTED, lp);
+           } else if (state == BluetoothProfile.STATE_DISCONNECTED &&
+                   (prevState == BluetoothProfile.STATE_CONNECTED ||
+                   prevState == BluetoothProfile.STATE_DISCONNECTING)) {
+                LinkProperties lp = new LinkProperties();
+                lp.setInterfaceName(iface);
+                mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_DISCONNECTED, lp);
             }
         }