/**
* BlueCove - Java library for Bluetooth
*
* Java docs licensed under the Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* (c) Copyright 2001, 2002 Motorola, Inc. ALL RIGHTS RESERVED.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @version $Id$
*/
package javax.bluetooth;
import java.io.IOException;
import javax.microedition.io.Connection;
import com.intel.bluetooth.DebugLog;
import com.intel.bluetooth.RemoteDeviceHelper;
import com.intel.bluetooth.UtilsJavaSE;
/**
* The <code>RemoteDevice</code> class represents a remote Bluetooth device.
* It provides basic information about a remote device including the device's
* Bluetooth address and its friendly name.
*
*/
public class RemoteDevice {
/**
* A bluetooth hex address
*/
private String addressStr;
/**
* A bluetooth address for internal use
*/
private long addressLong;
/**
* Creates a Bluetooth device based upon its address. The Bluetooth address
* must be 12 hex characters long. Valid characters are 0-9, a-f, and A-F.
* There is no preceding "0x" in the string. For example, valid Bluetooth
* addresses include but are not limited to:<BR>
* <code>008037144297</code><BR>
* <code>00af8300cd0b</code><BR>
* <code>014bd91DA8FC</code>
*
* @param address
* the address of the Bluetooth device as a 12 character hex
* string
*
* @exception NullPointerException
* if <code>address</code> is <code>null</code>
*
* @exception IllegalArgumentException
* if <code>address</code> is the address of the local
* device or is not a valid Bluetooth address
*/
protected RemoteDevice(String address) {
if (address == null) {
throw new NullPointerException("address is null");
}
if (address.length() != 12) {
throw new IllegalArgumentException("Malformed address: " + address + "; should be 12 characters");
}
if (address.startsWith("-")) {
throw new IllegalArgumentException("Malformed address: " + address + "; can't be negative");
}
DebugLog.debug("new RemoteDevice", address);
this.addressStr = RemoteDeviceHelper.formatBluetoothAddress(address);
try {
if (this.addressStr.equals(LocalDevice.getLocalDevice().getBluetoothAddress())) {
throw new IllegalArgumentException("can't use the LocalDevice address.");
}
} catch (BluetoothStateException e) {
throw (RuntimeException) UtilsJavaSE.initCause(new RuntimeException("Can't initialize bluetooth support"), e);
}
this.addressLong = RemoteDeviceHelper.getAddress(address);
}
/**
* Determines if this is a trusted device according to the BCC.
*
* @return <code>true</code> if the device is a trusted device, otherwise
* <code>false</code>
*/
public boolean isTrustedDevice() {
return RemoteDeviceHelper.implIsTrustedDevice(this);
}
/**
* Returns the name of this device. The Bluetooth specification calls this
* name the "Bluetooth device name" or the "user-friendly name". This method
* will only contact the remote device if the name is not known or
* <code>alwaysAsk</code> is <code>true</code>.
*
* @param alwaysAsk
* if <code>true</code> then the device will be contacted for
* its name, otherwise, if there exists a known name for this
* device, the name will be returned without contacting the
* remote device
*
* @return the name of the device, or <code>null</code> if the Bluetooth
* system does not support this feature; if the local device is able
* to contact the remote device, the result will never be
* <code>null</code>; if the remote device does not have a name
* then an empty string will be returned
*
* @exception IOException
* if the remote device can not be contacted or the remote
* device could not provide its name
*/
public String getFriendlyName(boolean alwaysAsk) throws IOException {
return RemoteDeviceHelper.implGetFriendlyName(this, this.addressLong, alwaysAsk);
}
/**
* Retrieves the Bluetooth address of this device. The Bluetooth address
* will be 12 characters long. Valid characters are 0-9 and A-F. This method
* will never return <code>null</code>.
*
* @return the Bluetooth address of the remote device
*/
public final String getBluetoothAddress() {
return this.addressStr;
}
/**
* Determines if two <code>RemoteDevice</code>s are equal. Two devices
* are equal if they have the same Bluetooth device address.
*
* @param obj
* the object to compare to
*
* @return <code>true</code> if both devices have the same Bluetooth
* address; <code>false</code> if both devices do not have the
* same address; <code>false</code> if <code>obj</code> is
* <code>null</code>; <code>false</code> if <code>obj</code>
* is not a <code>RemoteDevice</code>
*/
public boolean equals(Object obj) {
return obj != null && obj instanceof RemoteDevice && ((RemoteDevice) obj).addressLong == addressLong;
}
/**
* Computes the hash code for this object. This method will return the same
* value when it is called multiple times on the same object.
*
* @return the hash code for this object
*/
public int hashCode() {
return new Long(addressLong).hashCode();
}
/**
* Retrieves the Bluetooth device that is at the other end of the Bluetooth
* Serial Port Profile connection, L2CAP connection, or OBEX over RFCOMM
* connection provided. This method will never return <code>null</code>.
*
* @param conn
* the Bluetooth Serial Port connection, L2CAP connection, or
* OBEX over RFCOMM connection whose remote Bluetooth device is
* needed
*
* @return the remote device involved in the connection
*
* @exception IllegalArgumentException
* if <code>conn</code> is not a Bluetooth Serial Port
* Profile connection, L2CAP connection, or OBEX over RFCOMM
* connection; if <code>conn</code> is a
* <code>L2CAPConnectionNotifier</code>,
* <code>StreamConnectionNotifier</code>, or
* <code>SessionNotifier</code>
*
* @exception IOException
* if the connection is closed
*
* @exception NullPointerException
* if <code>conn</code> is <code>null</code>
*/
public static RemoteDevice getRemoteDevice(Connection conn) throws IOException {
return RemoteDeviceHelper.implGetRemoteDevice(conn);
}
/**
* Attempts to authenticate this <code>RemoteDevice</code>.
* Authentication is a means of verifying the identity of a remote device.
* Authentication involves a device-to-device challenge and response scheme
* that requires a 128-bit common secret link key derived from a PIN code
* shared by both devices. If either side's PIN code does not match, the
* authentication process fails and the method returns <code>false</code>.
* The method will also return <code>false</code> if authentication is
* incompatible with the current security settings of the local device
* established by the BCC, if the stack does not support authentication at
* all, or if the stack does not support authentication subsequent to
* connection establishment.
*
* <p>
* If this <code>RemoteDevice</code> has previously been authenticated,
* then this method returns <code>true</code> without attempting to
* re-authenticate this <code>RemoteDevice</code>.
*
* @return <code>true</code> if authentication is successful; otherwise
* <code>false</code>
*
* @exception IOException
* if there are no open connections between the local device
* and this <code>RemoteDevice</code>
*/
public boolean authenticate() throws IOException {
return RemoteDeviceHelper.authenticate(this);
}
/**
* Determines if this <code>RemoteDevice</code> should be allowed to
* continue to access the local service provided by the
* <code>Connection</code>. In Bluetooth, authorization is defined as the
* process of deciding if device X is allowed to access service Y. The
* implementation of the <code>authorize(Connection conn)</code> method
* asks the Bluetooth Control Center (BCC) to decide if it is acceptable for
* <code>RemoteDevice</code> to continue to access a local service over
* the connection <code>conn</code>. In devices with a user interface,
* the BCC is expected to consult with the user to obtain approval.
*
* <p>
* Some Bluetooth systems may allow the user to permanently authorize a
* remote device for all local services. When a device is authorized in this
* way, it is known as a "trusted device" -- see
* {@link #isTrustedDevice() isTrustedDevice()}.
*
* <p>
* The <code>authorize()</code> method will also check that the identity
* of the <code>RemoteDevice</code> can be verified through
* authentication. If this <code>RemoteDevice</code> has been authorized
* for <code>conn</code> previously, then this method returns
* <code>true</code> without attempting to re-authorize this
* <code>RemoteDevice</code>.
*
* @see #isTrustedDevice
*
* @param conn
* the connection that this <code>RemoteDevice</code> is using
* to access a local service
*
* @return <code>true</code> if this <code>RemoteDevice</code> is
* successfully authenticated and authorized, otherwise
* <code>false</code> if authentication or authorization fails
*
* @exception IllegalArgumentException
* if <code>conn</code> is not a connection to this
* <code>RemoteDevice</code>, or if the local device
* initiated the connection, i.e., the local device is the
* client rather than the server. This exception is also
* thrown if <code>conn</code> was created by
* <code>RemoteDevice</code> using a scheme other than
* <code>btspp</code>, <code>btl2cap</code>, or
* <code>btgoep</code>. This exception is thrown if
* <code>conn</code> is a notifier used by a server to wait
* for a client connection, since the notifier is not a
* connection to this <code>RemoteDevice</code>.
*
* @exception IOException
* if <code>conn</code> is closed
*/
public boolean authorize(javax.microedition.io.Connection conn) throws IOException {
return RemoteDeviceHelper.implAuthorize(this, conn);
}
/**
* Attempts to turn encryption on or off for an existing connection. In the
* case where the parameter <code>on</code> is <code>true</code>, this
* method will first authenticate this <code>RemoteDevice</code> if it has
* not already been authenticated. Then it will attempt to turn on
* encryption. If the connection is already encrypted then this method
* returns <code>true</code>. Otherwise, when the parameter
* <code>on</code> is <code>true</code>, either:
* <UL>
* <LI> the method succeeds in turning on encryption for the connection and
* returns <code>true</code>, or
* <LI> the method was unsuccessful in turning on encryption and returns
* <code>false</code>. This could happen because the stack does not
* support encryption or because encryption conflicts with the user's
* security settings for the device.
* </UL>
*
* <p>
* In the case where the parameter <code>on</code> is <code>false</code>,
* there are again two possible outcomes:
* <UL>
* <LI> encryption is turned off on the connection and <code>true</code>
* is returned, or
* <LI> encryption is left on for the connection and <code>false</code> is
* returned.
* </UL>
* Encryption may be left on following <code>encrypt(conn,
* false)</code>
* for a variety of reasons. The user's current security settings for the
* device may require encryption or the stack may not have a mechanism to
* turn off encryption. Also, the BCC may have determined that encryption
* will be kept on for the physical link to this <code>RemoteDevice</code>.
* The details of the BCC are implementation dependent, but encryption might
* be left on because other connections to the same device need encryption.
* (All of the connections over the same physical link must be encrypted if
* any of them are encrypted.)
*
* <p>
* While attempting to turn encryption off may not succeed immediately
* because other connections need encryption on, there may be a delayed
* effect. At some point, all of the connections over this physical link
* needing encryption could be closed or also have had the method
* <code>encrypt(conn, false)</code> invoked for them. In this case, the
* BCC may turn off encryption for all connections over this physical link.
* (The policy used by the BCC is implementation dependent.) It is
* recommended that applications do <code>encrypt(conn,
* false)</code> once
* they no longer need encryption to allow the BCC to determine if it can
* reduce the overhead on connections to this <code>RemoteDevice</code>.
*
* <p>
* The fact that <code>encrypt(conn, false)</code> may not succeed in
* turning off encryption has very few consequences for applications. The
* stack handles encryption and decryption, so the application does not have
* to do anything different depending on whether the connection is still
* encrypted or not.
*
* @param conn
* the connection whose need for encryption has changed
*
* @param on
* <code>true</code> attempts to turn on encryption;
* <code>false</code> attempts to turn off encryption
*
* @return <code>true</code> if the change succeeded, otherwise
* <code>false</code> if it failed
*
* @exception IOException
* if <code>conn</code> is closed
*
* @exception IllegalArgumentException
* if <code>conn</code> is not a connection to this
* <code>RemoteDevice</code>; if <code>conn</code> was
* created by the client side of the connection using a
* scheme other than <code>btspp</code>,
* <code>btl2cap</code>, or <code>btgoep</code> (for
* example, this exception will be thrown if
* <code>conn</code> was created using the
* <code>file</code> or <code>http</code> schemes.); if
* <code>conn</code> is a notifier used by a server to wait
* for a client connection, since the notifier is not a
* connection to this <code>RemoteDevice</code>
*/
public boolean encrypt(javax.microedition.io.Connection conn, boolean on) throws IOException {
return RemoteDeviceHelper.implEncrypt(this, conn, on);
}
/**
* Determines if this <code>RemoteDevice</code> has been authenticated.
* <P>
* A device may have been authenticated by this application or another
* application. Authentication applies to an ACL link between devices and
* not on a specific L2CAP, RFCOMM, or OBEX connection. Therefore, if
* <code>authenticate()</code> is performed when an L2CAP connection is
* made to device A, then <code>isAuthenticated()</code> may return
* <code>true</code> when tested as part of making an RFCOMM connection to
* device A.
*
* @return <code>true</code> if this <code>RemoteDevice</code> has
* previously been authenticated; <code>false</code> if it has not
* been authenticated or there are no open connections between the
* local device and this <code>RemoteDevice</code>
*/
public boolean isAuthenticated() {
return RemoteDeviceHelper.implIsAuthenticated(this);
}
/**
* Determines if this <code>RemoteDevice</code> has been authorized
* previously by the BCC of the local device to exchange data related to the
* service associated with the connection. Both clients and servers can call
* this method. However, for clients this method returns <code>false</code>
* for all legal values of the <code>conn</code> argument.
*
* @param conn
* a connection that this <code>RemoteDevice</code> is using to
* access a service or provide a service
*
* @return <code>true</code> if <code>conn</code> is a server-side
* connection and this <code>RemoteDevice</code> has been
* authorized; <code>false</code> if <code>conn</code> is a
* client-side connection, or a server-side connection that has not
* been authorized
*
* @exception IllegalArgumentException
* if <code>conn</code> is not a connection to this
* <code>RemoteDevice</code>; if <code>conn</code> was
* not created using one of the schemes <code>btspp</code>,
* <code>btl2cap</code>, or <code>btgoep</code>; or if
* <code>conn</code> is a notifier used by a server to wait
* for a client connection, since the notifier is not a
* connection to this <code>RemoteDevice</code>.
*
* @exception IOException
* if <code>conn</code> is closed
*/
public boolean isAuthorized(javax.microedition.io.Connection conn) throws IOException {
return RemoteDeviceHelper.implIsAuthorized(this, conn);
}
/**
* Determines if data exchanges with this <code>RemoteDevice</code> are
* currently being encrypted.
* <P>
* Encryption may have been previously turned on by this or another
* application. Encryption applies to an ACL link between devices and not on
* a specific L2CAP, RFCOMM, or OBEX connection. Therefore, if
* <code>encrypt()</code> is performed with the <code>on</code>
* parameter set to <code>true</code> when an L2CAP connection is made to
* device A, then <code>isEncrypted()</code> may return <code>true</code>
* when tested as part of making an RFCOMM connection to device A.
*
* @return <code>true</code> if data exchanges with this
* <code>RemoteDevice</code> are being encrypted;
* <code>false</code> if they are not being encrypted, or there
* are no open connections between the local device and this
* <code>RemoteDevice</code>
*/
public boolean isEncrypted() {
return RemoteDeviceHelper.implIsEncrypted(this);
}
}