Merge change 23462 into eclair

* changes:
  Add Bluetooth Device trust
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 0a71961..0ec3243 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -266,6 +266,33 @@
         return BluetoothError.ERROR_IPC;
     }
 
+    /**
+     * Get trust state of a remote device.
+     * @hide
+     */
+    public boolean getTrustState() {
+        try {
+            return sService.getTrustState(mAddress);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+        return false;
+    }
+
+    /**
+     * Set trust state for a remote device.
+     * @param value the trust state value (true or false)
+     * @hide
+     */
+    public boolean setTrust(boolean value) {
+        try {
+            return sService.setTrust(mAddress, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+        return false;
+    }
+
     /** @hide */
     public int getBluetoothClass() {
         try {
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 9e05a87..a11ceac 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -58,4 +58,6 @@
     boolean setPairingConfirmation(in String address, boolean confirm);
     boolean cancelPairingUserInput(in String address);
 
+    boolean setTrust(in String address, in boolean value);
+    boolean getTrustState(in String address);
 }
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 79a7cf8..8cef3a2 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -347,7 +347,12 @@
             } else {
                 mBluetoothService.getBondState().setBondState(address,
                         BluetoothDevice.BOND_NOT_BONDED);
+                mBluetoothService.setRemoteDeviceProperty(address, "Trusted", "false");
             }
+        } else if (name.equals("Trusted")) {
+            if (DBG)
+                log("set trust state succeded, value is  " + propValues[1]);
+            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
         }
     }
 
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 21104c8..b168850 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -885,6 +885,42 @@
     }
 
     /**
+     * Sets the remote device trust state.
+     *
+     * @return boolean to indicate operation success or fail
+     */
+    public synchronized boolean setTrust(String address, boolean value) {
+        if (!BluetoothDevice.checkBluetoothAddress(address)) {
+            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+            return false;
+        }
+
+        return setDevicePropertyBooleanNative(getObjectPathFromAddress(address), "Trusted",
+                value ? 1 : 0);
+    }
+
+    /**
+     * Gets the remote device trust state as boolean.
+     * Note: this value may be
+     * retrieved from cache if we retrieved the data before *
+     *
+     * @return boolean to indicate trust or untrust state
+     */
+    public synchronized boolean getTrustState(String address) {
+        if (!BluetoothDevice.checkBluetoothAddress(address)) {
+            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+            return false;
+        }
+
+        String val = getRemoteDeviceProperty(address, "Trusted");
+        if (val == null) {
+            return false;
+        } else {
+            return val.equals("true") ? true : false;
+        }
+    }
+
+    /**
      * Gets the remote major, minor classes encoded as a 32-bit
      * integer.
      *
@@ -1220,5 +1256,6 @@
     private native boolean setPasskeyNative(String address, int passkey, int nativeData);
     private native boolean setPairingConfirmationNative(String address, boolean confirm,
             int nativeData);
+    private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
 
 }
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index d1901b4..de921f1 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -646,6 +646,7 @@
         if (!msg) {
             LOGE("%s: Can't allocate new method call for GetProperties!",
                   __FUNCTION__);
+            env->ReleaseStringUTFChars(key, c_key);
             return JNI_FALSE;
         }
 
@@ -701,6 +702,60 @@
 #endif
 }
 
+static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path,
+                                               jstring key, void *value, jint type) {
+#ifdef HAVE_BLUETOOTH
+    LOGV(__FUNCTION__);
+    native_data_t *nat = get_native_data(env, object);
+    if (nat) {
+        DBusMessage *reply, *msg;
+        DBusMessageIter iter;
+        DBusError err;
+
+        const char *c_key = env->GetStringUTFChars(key, NULL);
+        const char *c_path = env->GetStringUTFChars(path, NULL);
+
+        dbus_error_init(&err);
+        msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
+                                          c_path, DBUS_DEVICE_IFACE, "SetProperty");
+        if (!msg) {
+            LOGE("%s: Can't allocate new method call for device SetProperty!", __FUNCTION__);
+            env->ReleaseStringUTFChars(key, c_key);
+            env->ReleaseStringUTFChars(path, c_path);
+            return JNI_FALSE;
+        }
+
+        dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID);
+        dbus_message_iter_init_append(msg, &iter);
+        append_variant(&iter, type, value);
+
+        reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
+        dbus_message_unref(msg);
+
+        env->ReleaseStringUTFChars(key, c_key);
+        env->ReleaseStringUTFChars(path, c_path);
+        if (!reply) {
+            if (dbus_error_is_set(&err)) {
+                LOG_AND_FREE_DBUS_ERROR(&err);
+            } else
+            LOGE("DBus reply is NULL in function %s", __FUNCTION__);
+            return JNI_FALSE;
+        }
+        return JNI_TRUE;
+    }
+#endif
+    return JNI_FALSE;
+}
+
+static jboolean setDevicePropertyBooleanNative(JNIEnv *env, jobject object,
+                                                     jstring path, jstring key, jint value) {
+#ifdef HAVE_BLUETOOTH
+    return setDevicePropertyNative(env, object, path, key,
+                                        (void *)&value, DBUS_TYPE_BOOLEAN);
+#else
+    return JNI_FALSE;
+#endif
+}
 
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
@@ -740,6 +795,8 @@
     {"setPinNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)setPinNative},
     {"cancelPairingUserInputNative", "(Ljava/lang/String;I)Z",
             (void *)cancelPairingUserInputNative},
+    {"setDevicePropertyBooleanNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
+            (void *)setDevicePropertyBooleanNative},
 };
 
 int register_android_server_BluetoothService(JNIEnv *env) {