Merge "Stop clat if it's no longer in use." into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index efc8c36..207a25d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -858,6 +858,7 @@
field public static final int resource = 16842789; // 0x1010025
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
+ field public static final int restrictedAccountType = 16843733; // 0x10103d5
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
@@ -4612,8 +4613,13 @@
method public boolean isEnabled();
method public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
+ method public boolean registerCallback(android.bluetooth.BluetoothAdapterCallback);
method public boolean setName(java.lang.String);
method public boolean startDiscovery();
+ method public boolean startLeScan();
+ method public boolean startLeScan(java.util.UUID[]);
+ method public void stopLeScan();
+ method public boolean unRegisterCallback(android.bluetooth.BluetoothAdapterCallback);
field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
@@ -4644,6 +4650,14 @@
field public static final int STATE_TURNING_ON = 11; // 0xb
}
+ public abstract class BluetoothAdapterCallback {
+ ctor public BluetoothAdapterCallback();
+ method public void onCallbackRegistration(int);
+ method public void onLeScan(android.bluetooth.BluetoothDevice, int, byte[]);
+ field public static final int CALLBACK_REGISTERED = 0; // 0x0
+ field public static final int CALLBACK_REGISTRATION_FAILURE = 1; // 0x1
+ }
+
public class BluetoothAssignedNumbers {
field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a
field public static final int ALCATEL = 36; // 0x24
@@ -4836,6 +4850,7 @@
}
public final class BluetoothDevice implements android.os.Parcelable {
+ method public android.bluetooth.BluetoothGatt connectGattServer(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public int describeContents();
@@ -4868,6 +4883,159 @@
field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
}
+ public final class BluetoothGatt implements android.bluetooth.BluetoothProfile {
+ method public void abortReliableWrite(android.bluetooth.BluetoothDevice);
+ method public boolean beginReliableWrite();
+ method public void disconnect();
+ method public boolean discoverServices();
+ method public boolean executeReliableWrite();
+ method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method public int getConnectionState(android.bluetooth.BluetoothDevice);
+ method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+ method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
+ method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
+ method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
+ method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method public boolean readRemoteRssi();
+ method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
+ method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
+ method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ field public static final int GATT_FAILURE = 0; // 0x0
+ field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
+ field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
+ field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd
+ field public static final int GATT_INVALID_OFFSET = 7; // 0x7
+ field public static final int GATT_READ_NOT_PERMITTED = 2; // 0x2
+ field public static final int GATT_REQUEST_NOT_SUPPORTED = 6; // 0x6
+ field public static final int GATT_SUCCESS = 0; // 0x0
+ field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
+ }
+
+ public abstract class BluetoothGattCallback {
+ ctor public BluetoothGattCallback();
+ method public void onCharacteristicChanged(android.bluetooth.BluetoothGattCharacteristic);
+ method public void onCharacteristicRead(android.bluetooth.BluetoothGattCharacteristic, int);
+ method public void onCharacteristicWrite(android.bluetooth.BluetoothGattCharacteristic, int);
+ method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
+ method public void onDescriptorRead(android.bluetooth.BluetoothGattDescriptor, int);
+ method public void onDescriptorWrite(android.bluetooth.BluetoothGattDescriptor, int);
+ method public void onReadRemoteRssi(android.bluetooth.BluetoothDevice, int, int);
+ method public void onReliableWriteCompleted(android.bluetooth.BluetoothDevice, int);
+ method public void onServicesDiscovered(android.bluetooth.BluetoothDevice, int);
+ }
+
+ public class BluetoothGattCharacteristic {
+ ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
+ method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
+ method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
+ method public java.lang.Float getFloatValue(int, int);
+ method public int getInstanceId();
+ method public java.lang.Integer getIntValue(int, int);
+ method public int getPermissions();
+ method public int getProperties();
+ method public android.bluetooth.BluetoothGattService getService();
+ method public java.lang.String getStringValue(int);
+ method public java.util.UUID getUuid();
+ method public byte[] getValue();
+ method public int getWriteType();
+ method public boolean setValue(byte[]);
+ method public boolean setValue(int, int, int);
+ method public boolean setValue(int, int, int, int);
+ method public boolean setValue(java.lang.String);
+ method public void setWriteType(int);
+ field public static final int FORMAT_FLOAT = 52; // 0x34
+ field public static final int FORMAT_SFLOAT = 50; // 0x32
+ field public static final int FORMAT_SINT16 = 34; // 0x22
+ field public static final int FORMAT_SINT32 = 36; // 0x24
+ field public static final int FORMAT_SINT8 = 33; // 0x21
+ field public static final int FORMAT_UINT16 = 18; // 0x12
+ field public static final int FORMAT_UINT32 = 20; // 0x14
+ field public static final int FORMAT_UINT8 = 17; // 0x11
+ field public static final int PERMISSION_READ = 1; // 0x1
+ field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
+ field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
+ field public static final int PERMISSION_WRITE = 16; // 0x10
+ field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
+ field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
+ field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
+ field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
+ field public static final int PROPERTY_BROADCAST = 1; // 0x1
+ field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
+ field public static final int PROPERTY_INDICATE = 32; // 0x20
+ field public static final int PROPERTY_NOTIFY = 16; // 0x10
+ field public static final int PROPERTY_READ = 2; // 0x2
+ field public static final int PROPERTY_SIGNED_WRITE = 64; // 0x40
+ field public static final int PROPERTY_WRITE = 8; // 0x8
+ field public static final int PROPERTY_WRITE_NO_RESPONSE = 4; // 0x4
+ field public static final int WRITE_TYPE_DEFAULT = 2; // 0x2
+ field public static final int WRITE_TYPE_NO_RESPONSE = 1; // 0x1
+ field public static final int WRITE_TYPE_SIGNED = 4; // 0x4
+ field protected java.util.List mDescriptors;
+ }
+
+ public class BluetoothGattDescriptor {
+ ctor public BluetoothGattDescriptor(java.util.UUID, int);
+ method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
+ method public int getPermissions();
+ method public java.util.UUID getUuid();
+ method public byte[] getValue();
+ method public boolean setValue(byte[]);
+ field public static final byte[] DISABLE_NOTIFICATION_VALUE;
+ field public static final byte[] ENABLE_INDICATION_VALUE;
+ field public static final byte[] ENABLE_NOTIFICATION_VALUE;
+ field public static final int PERMISSION_READ = 1; // 0x1
+ field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
+ field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
+ field public static final int PERMISSION_WRITE = 16; // 0x10
+ field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
+ field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
+ field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
+ field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
+ }
+
+ public final class BluetoothGattServer implements android.bluetooth.BluetoothProfile {
+ method public boolean addService(android.bluetooth.BluetoothGattService);
+ method public void cancelConnection(android.bluetooth.BluetoothDevice);
+ method public void clearServices();
+ method public boolean connect(android.bluetooth.BluetoothDevice, boolean);
+ method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method public int getConnectionState(android.bluetooth.BluetoothDevice);
+ method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+ method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
+ method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
+ method public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+ method public boolean removeService(android.bluetooth.BluetoothGattService);
+ method public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
+ }
+
+ public abstract class BluetoothGattServerCallback {
+ ctor public BluetoothGattServerCallback();
+ method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
+ method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
+ method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
+ method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor);
+ method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]);
+ method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
+ method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
+ }
+
+ public class BluetoothGattService {
+ ctor public BluetoothGattService(java.util.UUID, int);
+ method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
+ method public boolean addService(android.bluetooth.BluetoothGattService);
+ method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
+ method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
+ method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
+ method public int getInstanceId();
+ method public int getType();
+ method public java.util.UUID getUuid();
+ field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
+ field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
+ field protected java.util.List mCharacteristics;
+ field protected java.util.List mIncludedServices;
+ }
+
public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public int getConnectionState(android.bluetooth.BluetoothDevice);
@@ -4930,6 +5098,14 @@
method public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
}
+ public final class BluetoothManager {
+ method public android.bluetooth.BluetoothAdapter getAdapter();
+ method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
+ method public int getConnectionState(android.bluetooth.BluetoothDevice, int);
+ method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int, int[]);
+ method public android.bluetooth.BluetoothGattServer openGattServer(android.content.Context, android.bluetooth.BluetoothGattServerCallback);
+ }
+
public abstract interface BluetoothProfile {
method public abstract java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public abstract int getConnectionState(android.bluetooth.BluetoothDevice);
@@ -4937,6 +5113,8 @@
field public static final int A2DP = 2; // 0x2
field public static final java.lang.String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE";
field public static final java.lang.String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
+ field public static final int GATT = 7; // 0x7
+ field public static final int GATT_SERVER = 8; // 0x8
field public static final int HEADSET = 1; // 0x1
field public static final int HEALTH = 3; // 0x3
field public static final int STATE_CONNECTED = 2; // 0x2
@@ -5494,6 +5672,7 @@
field public static final int BIND_IMPORTANT = 64; // 0x40
field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
+ field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -6657,6 +6836,7 @@
method public abstract boolean addPermission(android.content.pm.PermissionInfo);
method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ method public android.content.Intent buildPermissionRequestIntent(java.lang.String...);
method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public abstract int checkPermission(java.lang.String, java.lang.String);
method public abstract int checkSignatures(java.lang.String, java.lang.String);
@@ -6716,7 +6896,6 @@
method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract deprecated void removePackageFromPreferred(java.lang.String);
method public abstract void removePermission(java.lang.String);
- method public android.content.Intent buildPermissionRequestIntent(java.lang.String...);
method public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
method public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
@@ -10306,10 +10485,12 @@
}
public class UsbDeviceConnection {
- method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int);
+ method public deprecated int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int);
+ method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int, int);
method public boolean claimInterface(android.hardware.usb.UsbInterface, boolean);
method public void close();
- method public int controlTransfer(int, int, int, int, byte[], int, int);
+ method public deprecated int controlTransfer(int, int, int, int, byte[], int, int);
+ method public int controlTransfer(int, int, int, int, byte[], int, int, int);
method public int getFileDescriptor();
method public byte[] getRawDescriptors();
method public java.lang.String getSerial();
@@ -16807,11 +16988,14 @@
method public void setUserRestriction(java.lang.String, boolean);
method public void setUserRestrictions(android.os.Bundle);
method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
+ field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
+ field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
+ field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
}
public abstract class Vibrator {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 944a533..bb9e19f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -896,7 +896,7 @@
* @param taskId The identifier of the task to be moved, as found in
* {@link RunningTaskInfo} or {@link RecentTaskInfo}.
* @param flags Additional operational flags, 0 or more of
- * {@link #MOVE_TASK_WITH_HOME}.
+ * {@link #MOVE_TASK_WITH_HOME}, {@link #MOVE_TASK_NO_USER_ACTION}.
*/
public void moveTaskToFront(int taskId, int flags) {
moveTaskToFront(taskId, flags, null);
@@ -911,7 +911,7 @@
* @param taskId The identifier of the task to be moved, as found in
* {@link RunningTaskInfo} or {@link RecentTaskInfo}.
* @param flags Additional operational flags, 0 or more of
- * {@link #MOVE_TASK_WITH_HOME}.
+ * {@link #MOVE_TASK_WITH_HOME}, {@link #MOVE_TASK_NO_USER_ACTION}.
* @param options Additional options for the operation, either null or
* as per {@link Context#startActivity(Intent, android.os.Bundle)
* Context.startActivity(Intent, Bundle)}.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 734d435..459e49c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -19,7 +19,7 @@
import com.android.internal.policy.PolicyManager;
import com.android.internal.util.Preconditions;
-import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -319,7 +319,7 @@
registerService(BLUETOOTH_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
- return BluetoothAdapter.getDefaultAdapter();
+ return new BluetoothManager(ctx);
}});
registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index b00bf09..2e9c9e3 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -22,7 +22,6 @@
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.RemoteException;
@@ -359,6 +358,8 @@
private IBluetooth mService;
private Handler mServiceRecordHandler;
+ private BluetoothAdapterCallback mCallback;
+ private int mClientIf;
/**
* Get a handle to the default local Bluetooth adapter.
@@ -1137,7 +1138,8 @@
* Get the profile proxy object associated with the profile.
*
* <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
- * or {@link BluetoothProfile#A2DP}. Clients must implement
+ * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
+ * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
* {@link BluetoothProfile.ServiceListener} to get notified of
* the connection status and to get the proxy object.
*
@@ -1166,12 +1168,6 @@
} else if (profile == BluetoothProfile.HEALTH) {
BluetoothHealth health = new BluetoothHealth(context, listener);
return true;
- } else if (profile == BluetoothProfile.GATT) {
- BluetoothGatt gatt = new BluetoothGatt(context, listener);
- return true;
- } else if (profile == BluetoothProfile.GATT_SERVER) {
- BluetoothGattServer gattServer = new BluetoothGattServer(context, listener);
- return true;
} else {
return false;
}
@@ -1411,4 +1407,230 @@
mProxyServiceStateCallbacks.remove(cb);
}
}
+
+ /**
+ * Register an callback to receive async results, such as LE scan result.
+ *
+ * <p>This is an asynchronous call. The callback
+ * {@link BluetoothAdapterCallback#onCallbackRegistration}
+ * is used to notify success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callback BluetootAdapter callback handler that will receive asynchronous callbacks.
+ * @return If true, the callback will be called to notify success or failure,
+ * false on immediate error
+ */
+ public boolean registerCallback(BluetoothAdapterCallback callback) {
+ try {
+ IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
+ mCallback = callback;
+ UUID uuid = UUID.randomUUID();
+ if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
+
+ iGatt.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return false;
+ }
+ }
+
+ /**
+ * Unregister the registered callback.
+ */
+ public boolean unRegisterCallback(BluetoothAdapterCallback callback) {
+ if (callback != mCallback) return false;
+ try {
+ IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
+
+ iGatt.unregisterClient(mClientIf);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return false;
+ }
+ }
+
+ /**
+ * Starts a scan for Bluetooth LE devices.
+ *
+ * <p>Results of the scan are reported using the
+ * {@link BluetoothAdapterCallback#onLeScan} callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @return true, if the scan was started successfully
+ */
+ public boolean startLeScan() {
+ if (DBG) Log.d(TAG, "startLeScan()");
+ if (mClientIf == 0) return false;
+
+ try {
+ IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
+ iGatt.startScan(mClientIf, false);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Starts a scan for Bluetooth LE devices, looking for devices that
+ * advertise given services.
+ *
+ * <p>Devices which advertise all specified services are reported using the
+ * {@link BluetoothAdapterCallback#onLeScan} callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param serviceUuids Array of services to look for
+ * @return true, if the scan was started successfully
+ */
+ public boolean startLeScan(UUID[] serviceUuids) {
+ if (DBG) Log.d(TAG, "startLeScan() - with UUIDs");
+ if (mClientIf == 0) return false;
+
+ try {
+ IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
+ ParcelUuid[] uuids = new ParcelUuid[serviceUuids.length];
+ for(int i = 0; i != uuids.length; ++i) {
+ uuids[i] = new ParcelUuid(serviceUuids[i]);
+ }
+ iGatt.startScanWithUuids(mClientIf, false, uuids);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Stops an ongoing Bluetooth LE device scan.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ */
+ public void stopLeScan() {
+ if (DBG) Log.d(TAG, "stopScan()");
+ if (mClientIf == 0) return;
+
+ try {
+ IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
+ iGatt.stopScan(mClientIf, false);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ /**
+ * Bluetooth GATT interface callbacks
+ */
+ private final IBluetoothGattCallback mBluetoothGattCallback =
+ new IBluetoothGattCallback.Stub() {
+ /**
+ * Application interface registered - app is ready to go
+ */
+ public void onClientRegistered(int status, int clientIf) {
+ if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
+ + " clientIf=" + clientIf);
+ mClientIf = clientIf;
+ mCallback.onCallbackRegistration(status == BluetoothGatt.GATT_SUCCESS ?
+ BluetoothAdapterCallback.CALLBACK_REGISTERED :
+ BluetoothAdapterCallback.CALLBACK_REGISTRATION_FAILURE);
+ }
+
+ public void onClientConnectionState(int status, int clientIf,
+ boolean connected, String address) {
+ // no op
+ }
+
+ /**
+ * Callback reporting an LE scan result.
+ * @hide
+ */
+ public void onScanResult(String address, int rssi, byte[] advData) {
+ if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
+
+ try {
+ mCallback.onLeScan(getRemoteDevice(address), rssi, advData);
+ } catch (Exception ex) {
+ Log.w(TAG, "Unhandled exception: " + ex);
+ }
+ }
+
+ public void onGetService(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid) {
+ // no op
+ }
+
+ public void onGetIncludedService(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int inclSrvcType, int inclSrvcInstId,
+ ParcelUuid inclSrvcUuid) {
+ // no op
+ }
+
+ public void onGetCharacteristic(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid,
+ int charProps) {
+ // no op
+ }
+
+ public void onGetDescriptor(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid,
+ ParcelUuid descUuid) {
+ // no op
+ }
+
+ public void onSearchComplete(String address, int status) {
+ // no op
+ }
+
+ public void onCharacteristicRead(String address, int status, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid, byte[] value) {
+ // no op
+ }
+
+ public void onCharacteristicWrite(String address, int status, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid) {
+ // no op
+ }
+
+ public void onNotify(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid,
+ byte[] value) {
+ // no op
+ }
+
+ public void onDescriptorRead(String address, int status, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid,
+ ParcelUuid descrUuid, byte[] value) {
+ // no op
+ }
+
+ public void onDescriptorWrite(String address, int status, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid,
+ ParcelUuid descrUuid) {
+ // no op
+ }
+
+ public void onExecuteWrite(String address, int status) {
+ // no op
+ }
+
+ public void onReadRemoteRssi(String address, int rssi, int status) {
+ // no op
+ }
+ };
+
}
diff --git a/core/java/android/bluetooth/BluetoothAdapterCallback.java b/core/java/android/bluetooth/BluetoothAdapterCallback.java
new file mode 100644
index 0000000..a726bc9
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAdapterCallback.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * This abstract class is used to implement {@link BluetoothAdapter} callbacks.
+ */
+public abstract class BluetoothAdapterCallback {
+
+ /**
+ * Indicates the callback has been registered successfully
+ */
+ public static final int CALLBACK_REGISTERED = 0;
+
+ /**
+ * Indicates the callback registration has failed
+ */
+ public static final int CALLBACK_REGISTRATION_FAILURE = 1;
+
+ /**
+ * Callback to inform change in registration state of the application.
+ *
+ * @param status Returns {@link #CALLBACK_REGISTERED} if the application
+ * was successfully registered.
+ */
+ public void onCallbackRegistration(int status) {
+ }
+
+ /**
+ * Callback reporting an LE device found during a device scan initiated
+ * by the {@link BluetoothAdapter#startLeScan} function.
+ *
+ * @param device Identifies the remote device
+ * @param rssi The RSSI value for the remote device as reported by the
+ * Bluetooth hardware. 0 if no RSSI value is available.
+ * @param scanRecord The content of the advertisement record offered by
+ * the remote device.
+ */
+ public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
old mode 100755
new mode 100644
index 4cc22b4..83e95ca
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1126,4 +1127,30 @@
return pinBytes;
}
+ /**
+ * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as any further GATT client operations.
+ * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+ * GATT client operations.
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param autoConnect Whether to directly connect to the remote device (false)
+ * or to automatically connect as soon as the remote
+ * device becomes available (true).
+ * @throws IllegalArgumentException if callback is null
+ */
+ public BluetoothGatt connectGattServer(Context context, boolean autoConnect,
+ BluetoothGattCallback callback) {
+ // TODO(Bluetooth) check whether platform support BLE
+ // Do the check here or in GattServer?
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ IBluetoothManager managerService = adapter.getBluetoothManager();
+ try {
+ IBluetoothGatt iGatt = managerService.getBluetoothGatt();
+ BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this);
+ gatt.connect(autoConnect, callback);
+ return gatt;
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return null;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 1e12025..f9ce6ea 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,8 +16,6 @@
package android.bluetooth;
-
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfile.ServiceListener;
@@ -39,42 +37,48 @@
import java.util.UUID;
/**
- * Public API for the Bluetooth Gatt Profile.
+ * Public API for the Bluetooth GATT Profile.
*
- * <p>This class provides Bluetooth Gatt functionality to enable communication
+ * <p>This class provides Bluetooth GATT functionality to enable communication
* with Bluetooth Smart or Smart Ready devices.
*
- * <p>BluetoothGatt is a proxy object for controlling the Bluetooth Service
- * via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
- * BluetoothGatt proxy object.
- *
* <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
- * and call {@link #registerApp} to register your application. Gatt capable
- * devices can be discovered using the {@link #startScan} function or the
- * regular Bluetooth device discovery process.
- * @hide
+ * and call {@link BluetoothDevice#connectGattServer} to get a instance of this class.
+ * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
+ * scan process.
*/
public final class BluetoothGatt implements BluetoothProfile {
private static final String TAG = "BluetoothGatt";
private static final boolean DBG = true;
+ private static final boolean VDBG = true;
- private Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
+ private final Context mContext;
private IBluetoothGatt mService;
private BluetoothGattCallback mCallback;
private int mClientIf;
private boolean mAuthRetry = false;
+ private BluetoothDevice mDevice;
+ private boolean mAutoConnect;
+ private int mConnState;
+ private final Object mStateLock = new Object();
+
+ private static final int CONN_STATE_IDLE = 0;
+ private static final int CONN_STATE_CONNECTING = 1;
+ private static final int CONN_STATE_CONNECTED = 2;
+ private static final int CONN_STATE_DISCONNECTING = 3;
private List<BluetoothGattService> mServices;
- /** A Gatt operation completed successfully */
+ /** A GATT operation failed */
+ public static final int GATT_FAILURE = 0;
+
+ /** A GATT operation completed successfully */
public static final int GATT_SUCCESS = 0;
- /** Gatt read operation is not permitted */
+ /** GATT read operation is not permitted */
public static final int GATT_READ_NOT_PERMITTED = 0x2;
- /** Gatt write operation is not permitted */
+ /** GATT write operation is not permitted */
public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
/** Insufficient authentication for a given operation */
@@ -111,55 +115,6 @@
/*package*/ static final int AUTHENTICATION_MITM = 2;
/**
- * Bluetooth state change handlers
- */
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (DBG) Log.d(TAG,"Unbinding service...");
- synchronized (mConnection) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } else {
- synchronized (mConnection) {
- if (mService == null) {
- if (DBG) Log.d(TAG,"Binding service...");
- if (!mContext.bindService(new Intent(IBluetoothGatt.class.getName()),
- mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth GATT Service");
- }
- }
- }
- }
- }
- };
-
- /**
- * Service binder handling
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothGatt.Stub.asInterface(service);
- ServiceListener serviceListener = mServiceListener;
- if (serviceListener != null) {
- serviceListener.onServiceConnected(BluetoothProfile.GATT, BluetoothGatt.this);
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- ServiceListener serviceListener = mServiceListener;
- if (serviceListener != null) {
- serviceListener.onServiceDisconnected(BluetoothProfile.GATT);
- }
- }
- };
-
- /**
* Bluetooth GATT interface callbacks
*/
private final IBluetoothGattCallback mBluetoothGattCallback =
@@ -171,11 +126,27 @@
public void onClientRegistered(int status, int clientIf) {
if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
+ " clientIf=" + clientIf);
+ if (VDBG) {
+ synchronized(mStateLock) {
+ if (mConnState != CONN_STATE_CONNECTING) {
+ Log.e(TAG, "Bad connection state: " + mConnState);
+ }
+ }
+ }
mClientIf = clientIf;
+ if (status != GATT_SUCCESS) {
+ mCallback.onConnectionStateChange(mDevice, GATT_FAILURE,
+ BluetoothProfile.STATE_DISCONNECTED);
+ synchronized(mStateLock) {
+ mConnState = CONN_STATE_IDLE;
+ }
+ return;
+ }
try {
- mCallback.onAppRegistered(status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
+ mService.clientConnect(mClientIf, mDevice.getAddress(),
+ !mAutoConnect); // autoConnect is inverse of "isDirect"
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
}
}
@@ -187,13 +158,24 @@
boolean connected, String address) {
if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
+ " clientIf=" + clientIf + " device=" + address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
+ BluetoothProfile.STATE_DISCONNECTED;
try {
- mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
- connected ? BluetoothProfile.STATE_CONNECTED
- : BluetoothProfile.STATE_DISCONNECTED);
+ mCallback.onConnectionStateChange(mDevice, status, profileState);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
+
+ synchronized(mStateLock) {
+ if (connected) {
+ mConnState = CONN_STATE_CONNECTED;
+ } else {
+ mConnState = CONN_STATE_IDLE;
+ }
+ }
}
/**
@@ -201,13 +183,7 @@
* @hide
*/
public void onScanResult(String address, int rssi, byte[] advData) {
- if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
-
- try {
- mCallback.onScanResult(mAdapter.getRemoteDevice(address), rssi, advData);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
+ // no op
}
/**
@@ -219,8 +195,10 @@
public void onGetService(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid) {
if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- mServices.add(new BluetoothGattService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType));
}
@@ -236,10 +214,12 @@
if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
+ " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device,
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice,
srvcUuid.getUuid(), srvcInstId, srvcType);
- BluetoothGattService includedService = getService(device,
+ BluetoothGattService includedService = getService(mDevice,
inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
if (service != null && includedService != null) {
@@ -260,8 +240,10 @@
if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service != null) {
service.addCharacteristic(new BluetoothGattCharacteristic(
@@ -281,8 +263,10 @@
ParcelUuid descUuid) {
if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -303,9 +287,11 @@
*/
public void onSearchComplete(String address, int status) {
if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
try {
- mCallback.onServicesDiscovered(device, status);
+ mCallback.onServicesDiscovered(mDevice, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
@@ -322,6 +308,9 @@
if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
+ " UUID=" + charUuid + " Status=" + status);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
&& mAuthRetry == false) {
@@ -338,8 +327,7 @@
mAuthRetry = false;
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -367,8 +355,10 @@
if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
+ " UUID=" + charUuid + " Status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -411,8 +401,10 @@
byte[] value) {
if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -439,8 +431,10 @@
ParcelUuid descrUuid, byte[] value) {
if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -486,8 +480,10 @@
ParcelUuid descrUuid) {
if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -529,9 +525,11 @@
public void onExecuteWrite(String address, int status) {
if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
+ " status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
try {
- mCallback.onReliableWriteCompleted(device, status);
+ mCallback.onReliableWriteCompleted(mDevice, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
@@ -544,43 +542,24 @@
public void onReadRemoteRssi(String address, int rssi, int status) {
if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
" rssi=" + rssi + " status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
try {
- mCallback.onReadRemoteRssi(device, rssi, status);
+ mCallback.onReadRemoteRssi(mDevice, rssi, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
}
};
- /**
- * Create a BluetoothGatt proxy object.
- */
- /*package*/ BluetoothGatt(Context context, ServiceListener l) {
+ /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
mContext = context;
- mServiceListener = l;
- mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mService = iGatt;
+ mDevice = device;
mServices = new ArrayList<BluetoothGattService>();
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothStateChangeCallback", re);
- }
- } else {
- Log.e(TAG, "Unable to get BluetoothManager interface.");
- throw new RuntimeException("BluetoothManager inactive");
- }
-
- //Bind to the service only if the Bluetooth is ON
- if(mAdapter.isEnabled()){
- if (!context.bindService(new Intent(IBluetoothGatt.class.getName()), mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth Gatt Service");
- }
- }
+ mConnState = CONN_STATE_IDLE;
}
/**
@@ -590,24 +569,6 @@
if (DBG) Log.d(TAG, "close()");
unregisterApp();
- mServiceListener = null;
-
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
- }
- }
-
- synchronized (mConnection) {
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- }
}
/**
@@ -629,18 +590,18 @@
/**
- * Register an application callback to start using Gatt.
+ * Register an application callback to start using GATT.
*
- * <p>This is an asynchronous call. The callback is used to notify
- * success or failure if the function returns true.
+ * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
+ * is used to notify success or failure if the function returns true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param callback Gatt callback handler that will receive asynchronous
- * callbacks.
- * @return true, if application was successfully registered.
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @return If true, the callback will be called to notify success or failure,
+ * false on immediate error
*/
- public boolean registerApp(BluetoothGattCallback callback) {
+ private boolean registerApp(BluetoothGattCallback callback) {
if (DBG) Log.d(TAG, "registerApp()");
if (mService == null) return false;
@@ -661,7 +622,7 @@
/**
* Unregister the current application and callbacks.
*/
- public void unregisterApp() {
+ private void unregisterApp() {
if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
if (mService == null || mClientIf == 0) return;
@@ -675,77 +636,7 @@
}
/**
- * Starts a scan for Bluetooth LE devices.
- *
- * <p>Results of the scan are reported using the
- * {@link BluetoothGattCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return true, if the scan was started successfully
- */
- public boolean startScan() {
- if (DBG) Log.d(TAG, "startScan()");
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.startScan(mClientIf, false);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Starts a scan for Bluetooth LE devices, looking for devices that
- * advertise given services.
- *
- * <p>Devices which advertise all specified services are reported using the
- * {@link BluetoothGattCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param serviceUuids Array of services to look for
- * @return true, if the scan was started successfully
- */
- public boolean startScan(UUID[] serviceUuids) {
- if (DBG) Log.d(TAG, "startScan() - with UUIDs");
- if (mService == null || mClientIf == 0) return false;
-
- try {
- ParcelUuid[] uuids = new ParcelUuid[serviceUuids.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(serviceUuids[i]);
- }
- mService.startScanWithUuids(mClientIf, false, uuids);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Stops an ongoing Bluetooth LE device scan.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- */
- public void stopScan() {
- if (DBG) Log.d(TAG, "stopScan()");
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.stopScan(mClientIf, false);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Initiate a connection to a Bluetooth Gatt capable device.
+ * Initiate a connection to a Bluetooth GATT capable device.
*
* <p>The connection may not be established right away, but will be
* completed when the remote device is available. A
@@ -757,7 +648,7 @@
* when the remote device is in range/available. Generally, the first ever
* connection to a device should be direct (autoConnect set to false) and
* subsequent connections to known devices should be invoked with the
- * autoConnect parameter set to false.
+ * autoConnect parameter set to true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
@@ -767,18 +658,24 @@
* device becomes available (true).
* @return true, if the connection attempt was initiated successfully
*/
- public boolean connect(BluetoothDevice device, boolean autoConnect) {
- if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.clientConnect(mClientIf, device.getAddress(),
- autoConnect ? false : true); // autoConnect is inverse of "isDirect"
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
+ /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
+ if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
+ synchronized(mStateLock) {
+ if (mConnState != CONN_STATE_IDLE) {
+ throw new IllegalStateException("Not idle");
+ }
+ mConnState = CONN_STATE_CONNECTING;
+ }
+ if (!registerApp(callback)) {
+ synchronized(mStateLock) {
+ mConnState = CONN_STATE_IDLE;
+ }
+ Log.e(TAG, "Failed to register callback");
return false;
}
+ // the connection will continue after successful callback registration
+ mAutoConnect = autoConnect;
return true;
}
@@ -787,18 +684,17 @@
* currently in progress.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote device
*/
- public void cancelConnection(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "cancelOpen() - device: " + device.getAddress());
+ public void disconnect() {
+ if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return;
try {
- mService.clientDisconnect(mClientIf, device.getAddress());
+ mService.clientDisconnect(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
+ // TBD deregister after conneciton is torn down
}
/**
@@ -812,17 +708,16 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device to explore
* @return true, if the remote service discovery has been started
*/
- public boolean discoverServices(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "discoverServices() - device: " + device.getAddress());
+ public boolean discoverServices() {
+ if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
mServices.clear();
try {
- mService.discoverServices(mClientIf, device.getAddress());
+ mService.discoverServices(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -839,16 +734,15 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return List of services on the remote device. Returns an empty list
* if service discovery has not yet been performed.
*/
- public List<BluetoothGattService> getServices(BluetoothDevice device) {
+ public List<BluetoothGattService> getServices() {
List<BluetoothGattService> result =
new ArrayList<BluetoothGattService>();
for (BluetoothGattService service : mServices) {
- if (service.getDevice().equals(device)) {
+ if (service.getDevice().equals(mDevice)) {
result.add(service);
}
}
@@ -868,14 +762,13 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @param uuid UUID of the requested service
* @return BluetoothGattService if supported, or null if the requested
* service is not offered by the remote device.
*/
- public BluetoothGattService getService(BluetoothDevice device, UUID uuid) {
+ public BluetoothGattService getService(UUID uuid) {
for (BluetoothGattService service : mServices) {
- if (service.getDevice().equals(device) &&
+ if (service.getDevice().equals(mDevice) &&
service.getUuid().equals(uuid)) {
return service;
}
@@ -923,8 +816,7 @@
}
/**
- * Writes a given characteristic and it's values to the associated remote
- * device.
+ * Writes a given characteristic and its values to the associated remote device.
*
* <p>Once the write operation has been completed, the
* {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
@@ -1061,15 +953,14 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return true, if the reliable write transaction has been initiated
*/
- public boolean beginReliableWrite(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + device.getAddress());
+ public boolean beginReliableWrite() {
+ if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.beginReliableWrite(mClientIf, device.getAddress());
+ mService.beginReliableWrite(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1089,15 +980,14 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return true, if the request to execute the transaction has been sent
*/
- public boolean executeReliableWrite(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + device.getAddress());
+ public boolean executeReliableWrite() {
+ if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.endReliableWrite(mClientIf, device.getAddress(), true);
+ mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1113,15 +1003,13 @@
* operations for a given remote device.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote device
*/
- public void abortReliableWrite(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + device.getAddress());
+ public void abortReliableWrite(BluetoothDevice mDevice) {
+ if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return;
try {
- mService.endReliableWrite(mClientIf, device.getAddress(), false);
+ mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
@@ -1172,12 +1060,12 @@
* remote device.
* @hide
*/
- public boolean refresh(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "refresh() - device: " + device.getAddress());
+ public boolean refresh() {
+ if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.refreshDevice(mClientIf, device.getAddress());
+ mService.refreshDevice(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1194,15 +1082,14 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return true, if the RSSI value has been requested successfully
*/
- public boolean readRemoteRssi(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "readRssi() - device: " + device.getAddress());
+ public boolean readRemoteRssi() {
+ if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.readRemoteRssi(mClientIf, device.getAddress());
+ mService.readRemoteRssi(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1212,98 +1099,38 @@
}
/**
- * Get the current connection state of the profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote bluetooth device.
- * @return State of the profile connection. One of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
+ * @throws UnsupportedOperationException
*/
@Override
public int getConnectionState(BluetoothDevice device) {
- if (DBG) Log.d(TAG,"getConnectionState()");
- if (mService == null) return STATE_DISCONNECTED;
-
- List<BluetoothDevice> connectedDevices = getConnectedDevices();
- for(BluetoothDevice connectedDevice : connectedDevices) {
- if (device.equals(connectedDevice)) {
- return STATE_CONNECTED;
- }
- }
-
- return STATE_DISCONNECTED;
+ throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
/**
- * Get connected devices for the Gatt profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) Log.d(TAG,"getConnectedDevices");
-
- List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
- if (mService == null) return connectedDevices;
-
- try {
- connectedDevices = mService.getDevicesMatchingConnectionStates(
- new int[] { BluetoothProfile.STATE_CONNECTED });
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return connectedDevices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getConnectedDevices instead.");
}
/**
- * Get a list of devices that match any of the given connection
- * states.
+ * Not supported - please use
+ * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
+ * with {@link BluetoothProfile#GATT} as first argument
*
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param states Array of states. States can be one of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
-
- List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
- if (mService == null) return devices;
-
- try {
- devices = mService.getDevicesMatchingConnectionStates(states);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return devices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
}
}
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index afa4539..c9e5fea 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -18,34 +18,10 @@
import android.bluetooth.BluetoothDevice;
-import android.util.Log;
-
/**
* This abstract class is used to implement {@link BluetoothGatt} callbacks.
- * @hide
*/
public abstract class BluetoothGattCallback {
- /**
- * Callback to inform change in registration state of the application.
- *
- * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the application
- * was successfully registered.
- */
- public void onAppRegistered(int status) {
- }
-
- /**
- * Callback reporting an LE device found during a device scan initiated
- * by the {@link BluetoothGatt#startScan} function.
- *
- * @param device Identifies the remote device
- * @param rssi The RSSI value for the remote device as reported by the
- * Bluetooth hardware. 0 if no RSSI value is available.
- * @param scanRecord The content of the advertisement record offered by
- * the remote device.
- */
- public void onScanResult(BluetoothDevice device, int rssi, byte[] scanRecord) {
- }
/**
* Callback indicating when a remote device has been connected or disconnected.
@@ -61,8 +37,8 @@
}
/**
- * Callback invoked when the list of remote services, characteristics and
- * descriptors for the remote device have been updated.
+ * Callback invoked when the list of remote services, characteristics and descriptors
+ * for the remote device have been updated, ie new services have been discovered.
*
* @param device Remote device
* @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
@@ -97,7 +73,7 @@
* @param status The result of the write operation
*/
public void onCharacteristicWrite(BluetoothGattCharacteristic characteristic,
- int status) {
+ int status) {
}
/**
@@ -113,23 +89,21 @@
* Callback reporting the result of a descriptor read operation.
*
* @param descriptor Descriptor that was read from the associated
- * remote device.
+ * remote device.
* @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
* was completed successfully
*/
- public void onDescriptorRead(BluetoothGattDescriptor descriptor,
- int status) {
+ public void onDescriptorRead(BluetoothGattDescriptor descriptor, int status) {
}
/**
* Callback indicating the result of a descriptor write operation.
*
* @param descriptor Descriptor that was writte to the associated
- * remote device.
+ * remote device.
* @param status The result of the write operation
*/
- public void onDescriptorWrite(BluetoothGattDescriptor descriptor,
- int status) {
+ public void onDescriptorWrite(BluetoothGattDescriptor descriptor, int status) {
}
/**
@@ -150,7 +124,7 @@
*
* @param device Identifies the remote device
* @param rssi The RSSI value for the remote device
- * @param status 0 if the RSSI was read successfully
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
*/
public void onReadRemoteRssi(BluetoothDevice device, int rssi, int status) {
}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index f44dc5c0..d63d97e 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -21,8 +21,7 @@
import java.util.UUID;
/**
- * Represents a Bluetooth Gatt Characteristic
- * @hide
+ * Represents a Bluetooth GATT Characteristic
*/
public class BluetoothGattCharacteristic {
@@ -119,7 +118,7 @@
public static final int WRITE_TYPE_NO_RESPONSE = 0x01;
/**
- * Write characteristic including and authenticated signature
+ * Write characteristic including authentication signature
*/
public static final int WRITE_TYPE_SIGNED = 0x04;
@@ -219,12 +218,30 @@
protected List<BluetoothGattDescriptor> mDescriptors;
/**
+ * Create a new BluetoothGattCharacteristic.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param uuid The UUID for this characteristic
+ * @param properties Properties of this characteristic
+ * @param permissions Permissions for this characteristic
+ */
+ public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
+ initCharacteristic(null, uuid, 0, properties, permissions);
+ }
+
+ /**
* Create a new BluetoothGattCharacteristic
* @hide
*/
/*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
UUID uuid, int instanceId,
int properties, int permissions) {
+ initCharacteristic(service, uuid, instanceId, properties, permissions);
+ }
+
+ private void initCharacteristic(BluetoothGattService service,
+ UUID uuid, int instanceId,
+ int properties, int permissions) {
mUuid = uuid;
mInstance = instanceId;
mProperties = properties;
@@ -249,11 +266,16 @@
}
/**
- * Add a descriptor to this characteristic
- * @hide
+ * Adds a descriptor to this characteristic.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param descriptor Descriptor to be added to this characteristic.
+ * @return true, if the descriptor was added to the characteristic
*/
- /*package*/ void addDescriptor(BluetoothGattDescriptor descriptor) {
+ public boolean addDescriptor(BluetoothGattDescriptor descriptor) {
mDescriptors.add(descriptor);
+ descriptor.setCharacteristic(this);
+ return true;
}
/**
@@ -265,8 +287,15 @@
}
/**
+ * Sets the service associated with this device.
+ * @hide
+ */
+ /*package*/ void setService(BluetoothGattService service) {
+ mService = service;
+ }
+
+ /**
* Returns the UUID of this characteristic
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this characteristic
*/
@@ -280,8 +309,6 @@
* <p>If a remote device offers multiple characteristics with the same UUID,
* the instance ID is used to distuinguish between characteristics.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Instance ID of this characteristic
*/
public int getInstanceId() {
@@ -294,8 +321,6 @@
* <p>The properties contain a bit mask of property flags indicating
* the features of this characteristic.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Properties of this characteristic
*/
public int getProperties() {
@@ -304,7 +329,6 @@
/**
* Returns the permissions for this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Permissions of this characteristic
*/
@@ -314,7 +338,6 @@
/**
* Gets the write type for this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Write type for this characteristic
*/
@@ -329,11 +352,6 @@
* {@link BluetoothGatt#writeCharacteristic} function write this
* characteristic.
*
- * <p>The default write type for a characteristic is
- * {@link #WRITE_TYPE_DEFAULT}.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param writeType The write type to for this characteristic. Can be one
* of:
* {@link #WRITE_TYPE_DEFAULT},
@@ -345,8 +363,15 @@
}
/**
+ * Set the desired key size.
+ * @hide
+ */
+ public void setKeySize(int keySize) {
+ mKeySize = keySize;
+ }
+
+ /**
* Returns a list of descriptors for this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Descriptors for this characteristic
*/
@@ -358,9 +383,7 @@
* Returns a descriptor with a given UUID out of the list of
* descriptors for this characteristic.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return Gatt descriptor object or null if no descriptor with the
+ * @return GATT descriptor object or null if no descriptor with the
* given UUID was found.
*/
public BluetoothGattDescriptor getDescriptor(UUID uuid) {
@@ -376,12 +399,10 @@
* Get the stored value for this characteristic.
*
* <p>This function returns the stored value for this characteristic as
- * retrieved by calling {@link BluetoothGatt#readCharacteristic}. To cached
+ * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
* value of the characteristic is updated as a result of a read characteristic
* operation or if a characteristic update notification has been received.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Cached value of the characteristic
*/
public byte[] getValue() {
@@ -397,8 +418,6 @@
* characteristic value at the given offset are interpreted to generate the
* return value.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param formatType The format type used to interpret the characteristic
* value.
* @param offset Offset at which the integer value can be found.
@@ -436,7 +455,6 @@
/**
* Return the stored value of this characteristic.
* <p>See {@link #getValue} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param formatType The format type used to interpret the characteristic
* value.
@@ -462,7 +480,7 @@
/**
* Return the stored value of this characteristic.
* <p>See {@link #getValue} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param offset Offset at which the string value can be found.
* @return Cached value of the characteristic
*/
@@ -481,8 +499,6 @@
* {@link BluetoothGatt#writeCharacteristic} to send the value to the
* remote device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param value New value for this characteristic
* @return true if the locally stored value has been set, false if the
* requested value could not be stored locally.
@@ -495,7 +511,6 @@
/**
* Set the locally stored value of this characteristic.
* <p>See {@link #setValue(byte[])} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param value New value for this characteristic
* @param formatType Integer format type used to transform the value parameter
@@ -542,7 +557,7 @@
/**
* Set the locally stored value of this characteristic.
* <p>See {@link #setValue(byte[])} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param mantissa Mantissa for this characteristic
* @param exponent exponent value for this characteristic
* @param formatType Float format type used to transform the value parameter
@@ -582,7 +597,7 @@
/**
* Set the locally stored value of this characteristic.
* <p>See {@link #setValue(byte[])} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param value New value for this characteristic
* @return true if the locally stored value has been set
*/
@@ -593,7 +608,6 @@
/**
* Returns the size of a give value type.
- * @hide
*/
private int getTypeLen(int formatType) {
return formatType & 0xF;
@@ -601,7 +615,6 @@
/**
* Convert a signed byte to an unsigned int.
- * @hide
*/
private int unsignedByteToInt(byte b) {
return b & 0xFF;
@@ -609,7 +622,6 @@
/**
* Convert signed bytes to a 16-bit unsigned int.
- * @hide
*/
private int unsignedBytesToInt(byte b0, byte b1) {
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
@@ -617,7 +629,6 @@
/**
* Convert signed bytes to a 32-bit unsigned int.
- * @hide
*/
private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
@@ -626,7 +637,6 @@
/**
* Convert signed bytes to a 16-bit short float value.
- * @hide
*/
private float bytesToFloat(byte b0, byte b1) {
int mantissa = unsignedToSigned(unsignedByteToInt(b0)
@@ -637,7 +647,6 @@
/**
* Convert signed bytes to a 32-bit short float value.
- * @hide
*/
private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
int mantissa = unsignedToSigned(unsignedByteToInt(b0)
@@ -649,7 +658,6 @@
/**
* Convert an unsigned integer value to a two's-complement encoded
* signed value.
- * @hide
*/
private int unsignedToSigned(int unsigned, int size) {
if ((unsigned & (1 << size-1)) != 0) {
@@ -660,7 +668,6 @@
/**
* Convert an integer into the signed bits of a given length.
- * @hide
*/
private int intToSignedBits(int i, int size) {
if (i < 0) {
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index ba1f28a..6ba2db7 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -19,8 +19,7 @@
import java.util.UUID;
/**
- * Represents a Bluetooth Gatt Descriptor
- * @hide
+ * Represents a Bluetooth GATT Descriptor
*/
public class BluetoothGattDescriptor {
@@ -109,12 +108,28 @@
* Create a new BluetoothGattDescriptor.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
+ * @param uuid The UUID for this descriptor
+ * @param permissions Permissions for this descriptor
+ */
+ public BluetoothGattDescriptor(UUID uuid, int permissions) {
+ initDescriptor(null, uuid, permissions);
+ }
+
+ /**
+ * Create a new BluetoothGattDescriptor.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param characteristic The characteristic this descriptor belongs to
* @param uuid The UUID for this descriptor
* @param permissions Permissions for this descriptor
*/
/*package*/ BluetoothGattDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
int permissions) {
+ initDescriptor(characteristic, uuid, permissions);
+ }
+
+ private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
+ int permissions) {
mCharacteristic = characteristic;
mUuid = uuid;
mPermissions = permissions;
@@ -129,8 +144,15 @@
}
/**
+ * Set the back-reference to the associated characteristic
+ * @hide
+ */
+ /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
+ mCharacteristic = characteristic;
+ }
+
+ /**
* Returns the UUID of this descriptor.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this descriptor
*/
@@ -140,7 +162,6 @@
/**
* Returns the permissions for this descriptor.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Permissions of this descriptor
*/
@@ -152,12 +173,10 @@
* Returns the stored value for this descriptor
*
* <p>This function returns the stored value for this descriptor as
- * retrieved by calling {@link BluetoothGatt#readDescriptor}. To cached
+ * retrieved by calling {@link BluetoothGatt#readDescriptor}. The cached
* value of the descriptor is updated as a result of a descriptor read
* operation.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Cached value of the descriptor
*/
public byte[] getValue() {
@@ -172,8 +191,6 @@
* {@link BluetoothGatt#writeDescriptor} to send the value to the
* remote device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param value New value for this descriptor
* @return true if the locally stored value has been set, false if the
* requested value could not be stored locally.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 6b69377..d1f4b82 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -38,88 +38,30 @@
import java.util.UUID;
/**
- * Public API for the Bluetooth Gatt Profile server role.
+ * Public API for the Bluetooth GATT Profile server role.
*
- * <p>This class provides Bluetooth Gatt server role functionality,
+ * <p>This class provides Bluetooth GATT server role functionality,
* allowing applications to create and advertise Bluetooth Smart services
* and characteristics.
*
* <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
* via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
* BluetoothGatt proxy object.
- * @hide
*/
public final class BluetoothGattServer implements BluetoothProfile {
private static final String TAG = "BluetoothGattServer";
private static final boolean DBG = true;
- private Context mContext;
- private ServiceListener mServiceListener;
+ private final Context mContext;
private BluetoothAdapter mAdapter;
private IBluetoothGatt mService;
private BluetoothGattServerCallback mCallback;
- private int mServerIf;
+ private Object mServerIfLock = new Object();
+ private int mServerIf;
private List<BluetoothGattService> mServices;
- /**
- * Bluetooth state change handlers
- */
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (DBG) Log.d(TAG,"Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (DBG) Log.d(TAG,"Binding service...");
- if (!mContext.bindService(new
- Intent(IBluetoothGatt.class.getName()),
- mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth GATT Service");
- }
- }
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
- }
- }
- }
- };
-
- /**
- * Service binder handling
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothGatt.Stub.asInterface(service);
- ServiceListener serviceListner = mServiceListener;
- if (serviceListner != null) {
- serviceListner.onServiceConnected(BluetoothProfile.GATT_SERVER,
- BluetoothGattServer.this);
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- ServiceListener serviceListner = mServiceListener;
- if (serviceListner != null) {
- serviceListner.onServiceDisconnected(BluetoothProfile.GATT_SERVER);
- }
- }
- };
+ private static final int CALLBACK_REG_TIMEOUT = 10000;
/**
* Bluetooth GATT interface callbacks
@@ -133,11 +75,14 @@
public void onServerRegistered(int status, int serverIf) {
if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status
+ " serverIf=" + serverIf);
- mServerIf = serverIf;
- try {
- mCallback.onAppRegistered(status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
+ synchronized(mServerIfLock) {
+ if (mCallback != null) {
+ mServerIf = serverIf;
+ mServerIfLock.notify();
+ } else {
+ // registration timeout
+ Log.e(TAG, "onServerRegistered: mCallback is null");
+ }
}
}
@@ -147,13 +92,7 @@
*/
public void onScanResult(String address, int rssi, byte[] advData) {
if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
-
- try {
- mCallback.onScanResult(mAdapter.getRemoteDevice(address),
- rssi, advData);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
+ // no op
}
/**
@@ -209,8 +148,7 @@
BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
if (service == null) return;
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid);
+ BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
if (characteristic == null) return;
try {
@@ -340,31 +278,13 @@
/**
* Create a BluetoothGattServer proxy object.
*/
- /*package*/ BluetoothGattServer(Context context, ServiceListener l) {
+ /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt) {
mContext = context;
- mServiceListener = l;
+ mService = iGatt;
mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mCallback = null;
+ mServerIf = 0;
mServices = new ArrayList<BluetoothGattService>();
-
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothStateChangeCallback", re);
- }
- } else {
- Log.e(TAG, "Unable to get BluetoothManager interface.");
- throw new RuntimeException("BluetoothManager inactive");
- }
-
- //Bind to the service only if the Bluetooth is ON
- if(mAdapter.isEnabled()){
- if (!context.bindService(new Intent(IBluetoothGatt.class.getName()), mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth Gatt Service");
- }
- }
}
/**
@@ -372,29 +292,75 @@
*/
/*package*/ void close() {
if (DBG) Log.d(TAG, "close()");
+ unregisterCallback();
+ }
- unregisterApp();
- mServiceListener = null;
+ /**
+ * Register an application callback to start using GattServer.
+ *
+ * <p>This is an asynchronous call. The callback is used to notify
+ * success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callback GATT callback handler that will receive asynchronous
+ * callbacks.
+ * @return true, the callback will be called to notify success or failure,
+ * false on immediate error
+ */
+ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
+ if (DBG) Log.d(TAG, "registerCallback()");
+ if (mService == null) {
+ Log.e(TAG, "GATT service not available");
+ return false;
+ }
+ UUID uuid = UUID.randomUUID();
+ if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
+ synchronized(mServerIfLock) {
+ if (mCallback != null) {
+ Log.e(TAG, "App can register callback only once");
+ return false;
+ }
+
+ mCallback = callback;
try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
+ mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ mCallback = null;
+ return false;
+ }
+
+ try {
+ mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "" + e);
+ mCallback = null;
+ }
+
+ if (mServerIf == 0) {
+ mCallback = null;
+ return false;
+ } else {
+ return true;
}
}
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
- }
+ /**
+ * Unregister the current application and callbacks.
+ */
+ private void unregisterCallback() {
+ if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
+ if (mService == null || mServerIf == 0) return;
+
+ try {
+ mCallback = null;
+ mService.unregisterServer(mServerIf);
+ mServerIf = 0;
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
}
}
@@ -414,123 +380,7 @@
}
/**
- * Register an application callback to start using Gatt.
- *
- * <p>This is an asynchronous call. The callback is used to notify
- * success or failure if the function returns true.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param callback Gatt callback handler that will receive asynchronous
- * callbacks.
- * @return true, if application was successfully registered.
- */
- public boolean registerApp(BluetoothGattServerCallback callback) {
- if (DBG) Log.d(TAG, "registerApp()");
- if (mService == null) return false;
-
- mCallback = callback;
- UUID uuid = UUID.randomUUID();
- if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
-
- try {
- mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Unregister the current application and callbacks.
- */
- public void unregisterApp() {
- if (DBG) Log.d(TAG, "unregisterApp() - mServerIf=" + mServerIf);
- if (mService == null || mServerIf == 0) return;
-
- try {
- mCallback = null;
- mService.unregisterServer(mServerIf);
- mServerIf = 0;
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Starts a scan for Bluetooth LE devices.
- *
- * <p>Results of the scan are reported using the
- * {@link BluetoothGattServerCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return true, if the scan was started successfully
- */
- public boolean startScan() {
- if (DBG) Log.d(TAG, "startScan()");
- if (mService == null || mServerIf == 0) return false;
-
- try {
- mService.startScan(mServerIf, true);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Starts a scan for Bluetooth LE devices, looking for devices that
- * advertise given services.
- *
- * <p>Devices which advertise all specified services are reported using the
- * {@link BluetoothGattServerCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param serviceUuids Array of services to look for
- * @return true, if the scan was started successfully
- */
- public boolean startScan(UUID[] serviceUuids) {
- if (DBG) Log.d(TAG, "startScan() - with UUIDs");
- if (mService == null || mServerIf == 0) return false;
-
- try {
- ParcelUuid[] uuids = new ParcelUuid[serviceUuids.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(serviceUuids[i]);
- }
- mService.startScanWithUuids(mServerIf, true, uuids);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Stops an ongoing Bluetooth LE device scan.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- */
- public void stopScan() {
- if (DBG) Log.d(TAG, "stopScan()");
- if (mService == null || mServerIf == 0) return;
-
- try {
- mService.stopScan(mServerIf, true);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Initiate a connection to a Bluetooth Gatt capable device.
+ * Initiate a connection to a Bluetooth GATT capable device.
*
* <p>The connection may not be established right away, but will be
* completed when the remote device is available. A
@@ -542,11 +392,10 @@
* when the remote device is in range/available. Generally, the first ever
* connection to a device should be direct (autoConnect set to false) and
* subsequent connections to known devices should be invoked with the
- * autoConnect parameter set to false.
+ * autoConnect parameter set to true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device to connect to
* @param autoConnect Whether to directly connect to the remote device (false)
* or to automatically connect as soon as the remote
* device becomes available (true).
@@ -590,7 +439,7 @@
* Send a response to a read or write request to a remote device.
*
* <p>This function must be invoked in when a remote read/write request
- * is received by one of these callback methots:
+ * is received by one of these callback methods:
*
* <ul>
* <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
@@ -662,17 +511,17 @@
}
/**
- * Add a service to the list of services to be advertised.
+ * Add a service to the list of services to be hosted.
*
* <p>Once a service has been addded to the the list, the service and it's
- * included characteristics will be advertised by the local device.
+ * included characteristics will be provided by the local device.
*
- * <p>If the local device is already advertising services when this function
+ * <p>If the local device has already exposed services when this function
* is called, a service update notification will be sent to all clients.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param service Service to be added to the list of services advertised
+ * @param service Service to be added to the list of services provided
* by this device.
* @return true, if the service has been added successfully
*/
@@ -721,11 +570,11 @@
}
/**
- * Removes a service from the list of services to be advertised.
+ * Removes a service from the list of services to be provided.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param service Service to beremoved.
+ * @param service Service to be removed.
* @return true, if the service has been removed
*/
public boolean removeService(BluetoothGattService service) {
@@ -749,7 +598,7 @@
}
/**
- * Remove all services from the list of advertised services.
+ * Remove all services from the list of provided services.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*/
public void clearServices() {
@@ -765,7 +614,7 @@
}
/**
- * Returns a list of GATT services offered bu this device.
+ * Returns a list of GATT services offered by this device.
*
* <p>An application must call {@link #addService} to add a serice to the
* list of services offered by this device.
@@ -802,99 +651,40 @@
return null;
}
+
/**
- * Get the current connection state of the profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote bluetooth device.
- * @return State of the profile connection. One of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
+ * @throws UnsupportedOperationException
*/
@Override
public int getConnectionState(BluetoothDevice device) {
- if (DBG) Log.d(TAG,"getConnectionState()");
- if (mService == null) return STATE_DISCONNECTED;
-
- List<BluetoothDevice> connectedDevices = getConnectedDevices();
- for(BluetoothDevice connectedDevice : connectedDevices) {
- if (device.equals(connectedDevice)) {
- return STATE_CONNECTED;
- }
- }
-
- return STATE_DISCONNECTED;
+ throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
/**
- * Get connected devices for the Gatt profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) Log.d(TAG,"getConnectedDevices");
-
- List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
- if (mService == null) return connectedDevices;
-
- try {
- connectedDevices = mService.getDevicesMatchingConnectionStates(
- new int[] { BluetoothProfile.STATE_CONNECTED });
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return connectedDevices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getConnectedDevices instead.");
}
/**
- * Get a list of devices that match any of the given connection
- * states.
+ * Not supported - please use
+ * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
+ * with {@link BluetoothProfile#GATT} as first argument
*
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param states Array of states. States can be one of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
-
- List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
- if (mService == null) return devices;
-
- try {
- devices = mService.getDevicesMatchingConnectionStates(states);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return devices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
}
}
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 4f608ff..f9f1d97 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -22,30 +22,8 @@
/**
* This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- * @hide
*/
public abstract class BluetoothGattServerCallback {
- /**
- * Callback to inform change in registration state of the application.
- *
- * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the application
- * was successfully registered.
- */
- public void onAppRegistered(int status) {
- }
-
- /**
- * Callback reporting an LE device found during a device scan initiated
- * by the {@link BluetoothGattServer#startScan} function.
- *
- * @param device Identifies the remote device
- * @param rssi The RSSI value for the remote device as reported by the
- * Bluetooth hardware. 0 if no RSSI value is available.
- * @param scanRecord The content of the advertisement record offered by
- * the remote device.
- */
- public void onScanResult(BluetoothDevice device, int rssi, byte[] scanRecord) {
- }
/**
* Callback indicating when a remote device has been connected or disconnected.
@@ -101,9 +79,9 @@
* @param value The value the client wants to assign to the characteristic
*/
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
+ BluetoothGattCharacteristic characteristic,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
}
/**
@@ -118,7 +96,7 @@
* @param descriptor Descriptor to be read
*/
public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattDescriptor descriptor) {
+ int offset, BluetoothGattDescriptor descriptor) {
}
/**
@@ -137,9 +115,9 @@
* @param value The value the client wants to assign to the descriptor
*/
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattDescriptor descriptor,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
+ BluetoothGattDescriptor descriptor,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
}
/**
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 6a3ce66e..c3b3cfe 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -22,8 +22,7 @@
import java.util.UUID;
/**
- * Represents a Bluetooth Gatt Service
- * @hide
+ * Represents a Bluetooth GATT Service
*/
public class BluetoothGattService {
@@ -81,9 +80,14 @@
/**
* Create a new BluetoothGattService.
- * @hide
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param uuid The UUID for this service
+ * @param serviceType The type of this service,
+ * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY} or
+ * {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
*/
- /*package*/ BluetoothGattService(UUID uuid, int serviceType) {
+ public BluetoothGattService(UUID uuid, int serviceType) {
mDevice = null;
mUuid = uuid;
mInstanceId = 0;
@@ -115,11 +119,28 @@
}
/**
- * Add a characteristic to this service.
- * @hide
+ * Add an included service to this service.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param service The service to be added
+ * @return true, if the included service was added to the service
*/
- /*package*/ void addCharacteristic(BluetoothGattCharacteristic characteristic) {
+ public boolean addService(BluetoothGattService service) {
+ mIncludedServices.add(service);
+ return true;
+ }
+
+ /**
+ * Add a characteristic to this service.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param characteristic The characteristics to be added
+ * @return true, if the characteristic was added to the service
+ */
+ public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
mCharacteristics.add(characteristic);
+ characteristic.setService(this);
+ return true;
}
/**
@@ -136,6 +157,15 @@
}
/**
+ * Force the instance ID.
+ * This is needed for conformance testing only.
+ * @hide
+ */
+ public void setInstanceId(int instanceId) {
+ mInstanceId = instanceId;
+ }
+
+ /**
* Get the handle count override (conformance testing.
* @hide
*/
@@ -144,6 +174,15 @@
}
/**
+ * Force the number of handles to reserve for this service.
+ * This is needed for conformance testing only.
+ * @hide
+ */
+ public void setHandles(int handles) {
+ mHandles = handles;
+ }
+
+ /**
* Add an included service to the internal map.
* @hide
*/
@@ -153,7 +192,6 @@
/**
* Returns the UUID of this service
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this service
*/
@@ -168,8 +206,6 @@
* (ex. multiple battery services for different batteries), the instance
* ID is used to distuinguish services.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Instance ID of this service
*/
public int getInstanceId() {
@@ -178,15 +214,13 @@
/**
* Get the type of this service (primary/secondary)
- * @hide
*/
public int getType() {
return mServiceType;
}
/**
- * Get the list of included Gatt services for this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ * Get the list of included GATT services for this service.
*
* @return List of included services or empty list if no included services
* were discovered.
@@ -197,7 +231,6 @@
/**
* Returns a list of characteristics included in this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Characteristics included in this service
*/
@@ -217,9 +250,7 @@
* UUID, the first instance of a characteristic with the given UUID
* is returned.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return Gatt characteristic object or null if no characteristic with the
+ * @return GATT characteristic object or null if no characteristic with the
* given UUID was found.
*/
public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
new file mode 100644
index 0000000..19083b5
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+package android.bluetooth;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * High level manager used to obtain an instance of an {@link BluetoothAdapter}
+ * and to conduct overall Bluetooth Management.
+ * <p>
+ * Use {@link android.content.Context#getSystemService(java.lang.String)}
+ * with {@link Context#BLUETOOTH_SERVICE} to create an {@link BluetoothManager},
+ * then call {@link #getAdapter} to obtain the {@link BluetoothAdapter}.
+ * <p>
+ * Alternately, you can just call the static helper
+ * {@link BluetoothAdapter#getDefaultAdapter()}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using BLUETOOTH, read the
+ * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
+ * </div>
+ *
+ * @see Context#getSystemService
+ * @see BluetoothAdapter#getDefaultAdapter()
+ */
+public final class BluetoothManager {
+ private static final String TAG = "BluetoothManager";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = true;
+
+ private final BluetoothAdapter mAdapter;
+
+ /**
+ * @hide
+ */
+ public BluetoothManager(Context context) {
+ context = context.getApplicationContext();
+ if (context == null) {
+ throw new IllegalArgumentException(
+ "context not associated with any application (using a mock context?)");
+ }
+ // Legacy api - getDefaultAdapter does not take in the context
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ }
+
+ /**
+ * Get the default BLUETOOTH Adapter for this device.
+ *
+ * @return the default BLUETOOTH Adapter
+ */
+ public BluetoothAdapter getAdapter() {
+ return mAdapter;
+ }
+
+ /**
+ * Get the current connection state of the profile to the remote device.
+ *
+ * <p>This is not specific to any application configuration but represents
+ * the connection state of the local Bluetooth adapter for certain profile.
+ * This can be used by applications like status bar which would just like
+ * to know the state of Bluetooth.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device Remote bluetooth device.
+ * @param profile GATT or GATT_SERVER
+ * @return State of the profile connection. One of
+ * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING},
+ * {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_DISCONNECTING}
+ */
+ public int getConnectionState(BluetoothDevice device, int profile) {
+ if (DBG) Log.d(TAG,"getConnectionState()");
+
+ List<BluetoothDevice> connectedDevices = getConnectedDevices(profile);
+ for(BluetoothDevice connectedDevice : connectedDevices) {
+ if (device.equals(connectedDevice)) {
+ return BluetoothProfile.STATE_CONNECTED;
+ }
+ }
+
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Get connected devices for the specified profile.
+ *
+ * <p> Return the set of devices which are in state {@link BluetoothProfile#STATE_CONNECTED}
+ *
+ * <p>This is not specific to any application configuration but represents
+ * the connection state of Bluetooth for this profile.
+ * This can be used by applications like status bar which would just like
+ * to know the state of Bluetooth.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param profile GATT or GATT_SERVER
+ * @return List of devices. The list will be empty on error.
+ */
+ public List<BluetoothDevice> getConnectedDevices(int profile) {
+ if (DBG) Log.d(TAG,"getConnectedDevices");
+ if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
+ throw new IllegalArgumentException("Profile not supported: " + profile);
+ }
+
+ List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
+
+ try {
+ IBluetoothManager managerService = mAdapter.getBluetoothManager();
+ IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
+ if (iGatt == null) return connectedDevices;
+
+ connectedDevices = iGatt.getDevicesMatchingConnectionStates(
+ new int[] { BluetoothProfile.STATE_CONNECTED });
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+
+ return connectedDevices;
+ }
+
+ /**
+ *
+ * Get a list of devices that match any of the given connection
+ * states.
+ *
+ * <p> If none of the devices match any of the given states,
+ * an empty list will be returned.
+ *
+ * <p>This is not specific to any application configuration but represents
+ * the connection state of the local Bluetooth adapter for this profile.
+ * This can be used by applications like status bar which would just like
+ * to know the state of the local adapter.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param profile GATT or GATT_SERVER
+ * @param states Array of states. States can be one of
+ * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING},
+ * {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_DISCONNECTING},
+ * @return List of devices. The list will be empty on error.
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) {
+ if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
+
+ if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
+ throw new IllegalArgumentException("Profile not supported: " + profile);
+ }
+
+ List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
+
+ try {
+ IBluetoothManager managerService = mAdapter.getBluetoothManager();
+ IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
+ if (iGatt == null) return devices;
+ devices = iGatt.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+
+ return devices;
+ }
+
+ /**
+ * Open a GATT Server
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as the results of any other GATT server operations.
+ * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
+ * to conduct GATT server operations.
+ * @param context App context
+ * @param callback GATT server callback handler that will receive asynchronous callbacks.
+ * @return BluetoothGattServer instance
+ */
+ public BluetoothGattServer openGattServer(Context context,
+ BluetoothGattServerCallback callback) {
+ if (context == null || callback == null) {
+ throw new IllegalArgumentException("null parameter: " + context + " " + callback);
+ }
+
+ // TODO(Bluetooth) check whether platform support BLE
+ // Do the check here or in GattServer?
+
+ try {
+ IBluetoothManager managerService = mAdapter.getBluetoothManager();
+ IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
+ if (iGatt == null) {
+ Log.e(TAG, "Fail to get GATT Server connection");
+ return null;
+ }
+ BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt);
+ Boolean regStatus = mGattServer.registerCallback(callback);
+ return regStatus? mGattServer : null;
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return null;
+ }
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 9ee202a..43079f4 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -89,13 +89,11 @@
/**
* GATT
- * @hide
*/
static public final int GATT = 7;
/**
* GATT_SERVER
- * @hide
*/
static public final int GATT_SERVER = 8;
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 43c2392..81c0a6a 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -21,6 +21,7 @@
import android.os.INetworkManagementService;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.DhcpResults;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@@ -28,7 +29,10 @@
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
+import android.os.Messenger;
+import android.text.TextUtils;
import android.util.Log;
import java.net.InterfaceAddress;
import android.net.LinkAddress;
@@ -36,8 +40,11 @@
import java.net.Inet4Address;
import android.os.SystemProperties;
+import com.android.internal.util.AsyncChannel;
+
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
/**
* This class tracks the data connection associated with Bluetooth
@@ -51,24 +58,29 @@
private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
private static final String TAG = "BluetoothTethering";
private static final boolean DBG = true;
- private static final boolean VDBG = false;
+ private static final boolean VDBG = true;
private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+ private final Object mLinkPropertiesLock = new Object();
private LinkProperties mLinkProperties;
+
private LinkCapabilities mLinkCapabilities;
+
+ private final Object mNetworkInfoLock = new Object();
private NetworkInfo mNetworkInfo;
private BluetoothPan mBluetoothPan;
- private static String mIface;
- private Thread mDhcpThread;
+ private static String mRevTetheredIface;
/* For sending events to connectivity service handler */
private Handler mCsHandler;
- private Context mContext;
- public static BluetoothTetheringDataTracker sInstance;
+ protected Context mContext;
+ private static BluetoothTetheringDataTracker sInstance;
+ private BtdtHandler mBtdtHandler;
+ private AtomicReference<AsyncChannel> mAsyncChannel = new AtomicReference<AsyncChannel>(null);
private BluetoothTetheringDataTracker() {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
@@ -108,6 +120,7 @@
if (adapter != null) {
adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
}
+ mBtdtHandler = new BtdtHandler(target.getLooper(), this);
}
private BluetoothProfile.ServiceListener mProfileServiceListener =
@@ -224,15 +237,19 @@
/**
* Fetch NetworkInfo for the network
*/
- public synchronized NetworkInfo getNetworkInfo() {
- return mNetworkInfo;
+ public NetworkInfo getNetworkInfo() {
+ synchronized (mNetworkInfoLock) {
+ return new NetworkInfo(mNetworkInfo);
+ }
}
/**
* Fetch LinkProperties for the network
*/
- public synchronized LinkProperties getLinkProperties() {
- return new LinkProperties(mLinkProperties);
+ public LinkProperties getLinkProperties() {
+ synchronized (mLinkPropertiesLock) {
+ return new LinkProperties(mLinkProperties);
+ }
}
/**
@@ -286,88 +303,68 @@
return count;
}
-
- private boolean readLinkProperty(String iface) {
- String DhcpPrefix = "dhcp." + iface + ".";
- String ip = SystemProperties.get(DhcpPrefix + "ipaddress");
- String dns1 = SystemProperties.get(DhcpPrefix + "dns1");
- String dns2 = SystemProperties.get(DhcpPrefix + "dns2");
- String gateway = SystemProperties.get(DhcpPrefix + "gateway");
- String mask = SystemProperties.get(DhcpPrefix + "mask");
- if(ip.isEmpty() || gateway.isEmpty()) {
- Log.e(TAG, "readLinkProperty, ip: " + ip + ", gateway: " + gateway + ", can not be empty");
- return false;
+ void startReverseTether(final LinkProperties linkProperties) {
+ if (linkProperties == null || TextUtils.isEmpty(linkProperties.getInterfaceName())) {
+ Log.e(TAG, "attempted to reverse tether with empty interface");
+ return;
}
- int PrefixLen = countPrefixLength(NetworkUtils.numericToInetAddress(mask).getAddress());
- mLinkProperties.addLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(ip), PrefixLen));
- RouteInfo ri = new RouteInfo(NetworkUtils.numericToInetAddress(gateway));
- mLinkProperties.addRoute(ri);
- if(!dns1.isEmpty())
- mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns1));
- if(!dns2.isEmpty())
- mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns2));
- mLinkProperties.setInterfaceName(iface);
- return true;
- }
- public synchronized void startReverseTether(String iface) {
- mIface = iface;
- if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
- mDhcpThread = new Thread(new Runnable() {
+ synchronized (mLinkPropertiesLock) {
+ if (mLinkProperties.getInterfaceName() != null) {
+ Log.e(TAG, "attempted to reverse tether while already in process");
+ return;
+ }
+ mLinkProperties = linkProperties;
+ }
+ Thread dhcpThread = new Thread(new Runnable() {
public void run() {
- //TODO(): Add callbacks for failure and success case.
//Currently this thread runs independently.
- if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
- String DhcpResultName = "dhcp." + mIface + ".result";;
- String result = "";
- if (VDBG) Log.d(TAG, "waiting for change of sys prop dhcp result: " + DhcpResultName);
- for(int i = 0; i < 30*5; i++) {
- try { Thread.sleep(200); } catch (InterruptedException ie) { return;}
- result = SystemProperties.get(DhcpResultName);
- if (VDBG) Log.d(TAG, "read " + DhcpResultName + ": " + result);
- if(result.equals("failed")) {
- Log.e(TAG, "startReverseTether, failed to start dhcp service");
+ DhcpResults dhcpResults = new DhcpResults();
+ boolean success = NetworkUtils.runDhcp(linkProperties.getInterfaceName(),
+ dhcpResults);
+ synchronized (mLinkPropertiesLock) {
+ if (linkProperties.getInterfaceName() != mLinkProperties.getInterfaceName()) {
+ Log.e(TAG, "obsolete DHCP run aborted");
return;
}
- if(result.equals("ok")) {
- if (VDBG) Log.d(TAG, "startReverseTether, dhcp resut: " + result);
- if(readLinkProperty(mIface)) {
-
- mNetworkInfo.setIsAvailable(true);
- mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
-
- if (VDBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
- if(mCsHandler != null) {
- Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
- msg.sendToTarget();
-
- msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
- msg.sendToTarget();
- }
- }
+ if (!success) {
+ Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
return;
}
+ mLinkProperties = dhcpResults.linkProperties;
+ synchronized (mNetworkInfoLock) {
+ mNetworkInfo.setIsAvailable(true);
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+ if (mCsHandler != null) {
+ Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
+ new NetworkInfo(mNetworkInfo));
+ msg.sendToTarget();
+ }
+ }
+ return;
}
- Log.e(TAG, "startReverseTether, dhcp failed, resut: " + result);
}
});
- mDhcpThread.start();
+ dhcpThread.start();
}
- public synchronized void stopReverseTether() {
- //NetworkUtils.stopDhcp(iface);
- if(mDhcpThread != null && mDhcpThread.isAlive()) {
- mDhcpThread.interrupt();
- try { mDhcpThread.join(); } catch (InterruptedException ie) { return; }
+ void stopReverseTether() {
+ synchronized (mLinkPropertiesLock) {
+ if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) {
+ Log.e(TAG, "attempted to stop reverse tether with nothing tethered");
+ return;
+ }
+ NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName());
+ mLinkProperties.clear();
+ synchronized (mNetworkInfoLock) {
+ mNetworkInfo.setIsAvailable(false);
+ mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+
+ if (mCsHandler != null) {
+ mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)).
+ sendToTarget();
+ }
+ }
}
- mLinkProperties.clear();
- mNetworkInfo.setIsAvailable(false);
- mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
-
- Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
- msg.sendToTarget();
-
- msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
- msg.sendToTarget();
}
public void setDependencyMet(boolean met) {
@@ -383,4 +380,54 @@
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
+
+ static class BtdtHandler extends Handler {
+ private AsyncChannel mStackChannel;
+ private final BluetoothTetheringDataTracker mBtdt;
+
+ BtdtHandler(Looper looper, BluetoothTetheringDataTracker parent) {
+ super(looper);
+ mBtdt = parent;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (VDBG) Log.d(TAG, "got CMD_CHANNEL_HALF_CONNECTED");
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ AsyncChannel ac = (AsyncChannel)msg.obj;
+ if (mBtdt.mAsyncChannel.compareAndSet(null, ac) == false) {
+ Log.e(TAG, "Trying to set mAsyncChannel twice!");
+ } else {
+ ac.sendMessage(
+ AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ }
+ }
+ break;
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+ if (VDBG) Log.d(TAG, "got CMD_CHANNEL_DISCONNECTED");
+ mBtdt.stopReverseTether();
+ mBtdt.mAsyncChannel.set(null);
+ break;
+ case NetworkStateTracker.EVENT_NETWORK_CONNECTED:
+ LinkProperties linkProperties = (LinkProperties)(msg.obj);
+ if (VDBG) Log.d(TAG, "got EVENT_NETWORK_CONNECTED, " + linkProperties);
+ mBtdt.startReverseTether(linkProperties);
+ break;
+ case NetworkStateTracker.EVENT_NETWORK_DISCONNECTED:
+ linkProperties = (LinkProperties)(msg.obj);
+ if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties);
+ mBtdt.stopReverseTether();
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void supplyMessenger(Messenger messenger) {
+ if (messenger != null) {
+ new AsyncChannel().connect(mContext, mBtdtHandler, messenger);
+ }
+ }
}
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
old mode 100755
new mode 100644
index ed8777c..493d2f8
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManagerCallback;
import android.bluetooth.IBluetoothStateChangeCallback;
@@ -35,6 +36,7 @@
boolean enable();
boolean enableNoAutoConnect();
boolean disable(boolean persist);
+ IBluetoothGatt getBluetoothGatt();
String getAddress();
String getName();
diff --git a/core/java/android/bluetooth/MutableBluetoothGattCharacteristic.java b/core/java/android/bluetooth/MutableBluetoothGattCharacteristic.java
deleted file mode 100644
index c05abb2..0000000
--- a/core/java/android/bluetooth/MutableBluetoothGattCharacteristic.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed 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.
- */
-package android.bluetooth;
-
-import java.util.ArrayList;
-import java.util.IllegalFormatConversionException;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Mutable variant of a Bluetooth Gatt Characteristic
- * @hide
- */
-public class MutableBluetoothGattCharacteristic extends BluetoothGattCharacteristic {
-
- /**
- * Create a new MutableBluetoothGattCharacteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param uuid The UUID for this characteristic
- * @param properties Properties of this characteristic
- * @param permissions Permissions for this characteristic
- */
- public MutableBluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
- super(null, uuid, 0, properties, permissions);
- }
-
- /**
- * Adds a descriptor to this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param descriptor Descriptor to be added to this characteristic.
- */
- public void addDescriptor(MutableBluetoothGattDescriptor descriptor) {
- mDescriptors.add(descriptor);
- descriptor.setCharacteristic(this);
- }
-
- /**
- * Set the desired key size.
- * @hide
- */
- public void setKeySize(int keySize) {
- mKeySize = keySize;
- }
-
- /**
- * Sets the service associated with this device.
- * @hide
- */
- /*package*/ void setService(BluetoothGattService service) {
- mService = service;
- }
-}
diff --git a/core/java/android/bluetooth/MutableBluetoothGattDescriptor.java b/core/java/android/bluetooth/MutableBluetoothGattDescriptor.java
deleted file mode 100644
index e455392..0000000
--- a/core/java/android/bluetooth/MutableBluetoothGattDescriptor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed 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.
- */
-
-package android.bluetooth;
-
-import java.util.UUID;
-
-/**
- * Mutable variant of a Bluetooth Gatt Descriptor
- * @hide
- */
-public class MutableBluetoothGattDescriptor extends BluetoothGattDescriptor {
-
- /**
- * Create a new BluetoothGattDescriptor.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param uuid The UUID for this descriptor
- * @param permissions Permissions for this descriptor
- */
- public MutableBluetoothGattDescriptor(UUID uuid, int permissions) {
- super(null, uuid, permissions);
- }
-
- /**
- * Set the back-reference to the associated characteristic
- * @hide
- */
- /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
- mCharacteristic = characteristic;
- }
-}
diff --git a/core/java/android/bluetooth/MutableBluetoothGattService.java b/core/java/android/bluetooth/MutableBluetoothGattService.java
deleted file mode 100644
index 927f5ab..0000000
--- a/core/java/android/bluetooth/MutableBluetoothGattService.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed 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.
- */
-package android.bluetooth;
-
-import android.bluetooth.BluetoothDevice;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth Gatt Service
- * @hide
- */
-public class MutableBluetoothGattService extends BluetoothGattService {
-
- /**
- * Create a new MutableBluetoothGattService.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param uuid The UUID for this service
- * @param serviceType The type of this service (primary/secondary)
- */
- public MutableBluetoothGattService(UUID uuid, int serviceType) {
- super(uuid, serviceType);
- }
-
- /**
- * Add an included service to this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param service The service to be added
- * @return true, if the included service was added to the service
- */
- public boolean addService(BluetoothGattService service) {
- mIncludedServices.add(service);
- return true;
- }
-
- /**
- * Add a characteristic to this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param characteristic The characteristics to be added
- * @return true, if the characteristic was added to the service
- */
- public boolean addCharacteristic(MutableBluetoothGattCharacteristic characteristic) {
- mCharacteristics.add(characteristic);
- characteristic.setService(this);
- return true;
- }
-
- /**
- * Force the instance ID.
- * This is needed for conformance testing only.
- * @hide
- */
- public void setInstanceId(int instanceId) {
- mInstanceId = instanceId;
- }
-
- /**
- * Force the number of handles to reserve for this service.
- * This is needed for conformance testing only.
- * @hide
- */
- public void setHandles(int handles) {
- mHandles = handles;
- }
-}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7dd76cd..ef9b0bf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2203,7 +2203,6 @@
* {@link android.bluetooth.BluetoothAdapter} for using Bluetooth.
*
* @see #getSystemService
- * @hide
*/
public static final String BLUETOOTH_SERVICE = "bluetooth";
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index a318cf1..fb539c5 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -221,6 +221,9 @@
/** @hide */
public boolean requiredForAllUsers;
+ /** @hide */
+ public String restrictedAccountType;
+
public PackageInfo() {
}
@@ -262,6 +265,7 @@
dest.writeTypedArray(reqFeatures, parcelableFlags);
dest.writeInt(installLocation);
dest.writeInt(requiredForAllUsers ? 1 : 0);
+ dest.writeString(restrictedAccountType);
}
public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -301,5 +305,6 @@
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
installLocation = source.readInt();
requiredForAllUsers = source.readInt() != 0;
+ restrictedAccountType = source.readString();
}
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9afbe6f..da15e3b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2862,16 +2862,16 @@
/**
* @deprecated This function no longer does anything; it was an old
- * approach to managing preferred activities, which has been superceeded
- * (and conflicts with) the modern activity-based preferences.
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
*/
@Deprecated
public abstract void addPackageToPreferred(String packageName);
/**
* @deprecated This function no longer does anything; it was an old
- * approach to managing preferred activities, which has been superceeded
- * (and conflicts with) the modern activity-based preferences.
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
*/
@Deprecated
public abstract void removePackageFromPreferred(String packageName);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c311656..11f9be93 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -290,6 +290,7 @@
pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
pi.installLocation = p.installLocation;
pi.requiredForAllUsers = p.mRequiredForAllUsers;
+ pi.restrictedAccountType = p.mRestrictedAccountType;
pi.firstInstallTime = firstInstallTime;
pi.lastUpdateTime = lastUpdateTime;
if ((flags&PackageManager.GET_GIDS) != 0) {
@@ -1764,6 +1765,11 @@
false)) {
owner.mRequiredForAllUsers = true;
}
+ String accountType = sa.getString(com.android.internal.R.styleable
+ .AndroidManifestApplication_restrictedAccountType);
+ if (accountType != null && accountType.length() > 0) {
+ owner.mRestrictedAccountType = accountType;
+ }
}
if (sa.getBoolean(
@@ -3191,6 +3197,7 @@
}
public final static class Package {
+
public String packageName;
// For now we only support one application per package.
@@ -3278,6 +3285,9 @@
/* An app that's required for all users and cannot be uninstalled for a user */
public boolean mRequiredForAllUsers;
+ /* The restricted account authenticator type that is used by this application */
+ public String mRestrictedAccountType;
+
/**
* Digest suitable for comparing whether this package's manifest is the
* same as another.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index c0d2fae..7f94794 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -572,7 +572,10 @@
* are received faster. The value must be one of
* {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
* {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
- * or, the desired delay between events in microsecond.
+ * or, the desired delay between events in microseconds.
+ * Specifying the delay in microseconds only works from Android
+ * 2.3 (API level 9) onwards. For earlier releases, you must use
+ * one of the {@code SENSOR_DELAY_*} constants.
*
* @return <code>true</code> if the sensor is supported and successfully
* enabled.
@@ -604,7 +607,10 @@
* are received faster. The value must be one of
* {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
* {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
- * or, the desired delay between events in microsecond.
+ * or, the desired delay between events in microseconds.
+ * Specifying the delay in microseconds only works from Android
+ * 2.3 (API level 9) onwards. For earlier releases, you must use
+ * one of the {@code SENSOR_DELAY_*} constants.
*
* @param handler
* The {@link android.os.Handler Handler} the
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index b536490..0856e27 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -17,7 +17,6 @@
package android.hardware.usb;
import android.os.ParcelFileDescriptor;
-import android.util.Log;
import java.io.FileDescriptor;
@@ -119,10 +118,41 @@
* @param timeout in milliseconds
* @return length of data transferred (or zero) for success,
* or negative value for failure
+ *
+ * @deprecated Use {@link #controlTransfer(int, int, int, int, byte[], int, int, int)}
+ * which accepts a buffer start index.
*/
+ @Deprecated
public int controlTransfer(int requestType, int request, int value,
int index, byte[] buffer, int length, int timeout) {
- return native_control_request(requestType, request, value, index, buffer, length, timeout);
+ return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout);
+ }
+
+ /**
+ * Performs a control transaction on endpoint zero for this device.
+ * The direction of the transfer is determined by the request type.
+ * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is
+ * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write,
+ * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer
+ * is a read.
+ *
+ * @param requestType request type for this transaction
+ * @param request request ID for this transaction
+ * @param value value field for this transaction
+ * @param index index field for this transaction
+ * @param buffer buffer for data portion of transaction,
+ * or null if no data needs to be sent or received
+ * @param start the index of the first byte in the buffer to send or receive
+ * @param length the length of the data to send or receive
+ * @param timeout in milliseconds
+ * @return length of data transferred (or zero) for success,
+ * or negative value for failure
+ */
+ public int controlTransfer(int requestType, int request, int value, int index,
+ byte[] buffer, int start, int length, int timeout) {
+ checkBounds(buffer, start, length);
+ return native_control_request(requestType, request, value, index,
+ buffer, start, length, timeout);
}
/**
@@ -130,14 +160,37 @@
* The direction of the transfer is determined by the direction of the endpoint
*
* @param endpoint the endpoint for this transaction
- * @param buffer buffer for data to send or receive,
+ * @param buffer buffer for data to send or receive
+ * @param length the length of the data to send or receive
+ * @param timeout in milliseconds
+ * @return length of data transferred (or zero) for success,
+ * or negative value for failure
+ *
+ * @deprecated Use {@link #bulkTransfer(UsbEndpoint, byte[], int, int, int)}
+ * which accepts a buffer start index.
+ */
+ @Deprecated
+ public int bulkTransfer(UsbEndpoint endpoint,
+ byte[] buffer, int length, int timeout) {
+ return bulkTransfer(endpoint, buffer, 0, length, timeout);
+ }
+
+ /**
+ * Performs a bulk transaction on the given endpoint.
+ * The direction of the transfer is determined by the direction of the endpoint
+ *
+ * @param endpoint the endpoint for this transaction
+ * @param buffer buffer for data to send or receive
+ * @param start the index of the first byte in the buffer to send or receive
* @param length the length of the data to send or receive
* @param timeout in milliseconds
* @return length of data transferred (or zero) for success,
* or negative value for failure
*/
- public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) {
- return native_bulk_request(endpoint.getAddress(), buffer, length, timeout);
+ public int bulkTransfer(UsbEndpoint endpoint,
+ byte[] buffer, int start, int length, int timeout) {
+ checkBounds(buffer, start, length);
+ return native_bulk_request(endpoint.getAddress(), buffer, start, length, timeout);
}
/**
@@ -168,6 +221,13 @@
return native_get_serial();
}
+ private static void checkBounds(byte[] buffer, int start, int length) {
+ final int bufferLength = (buffer != null ? buffer.length : 0);
+ if (start < 0 || start + length > bufferLength) {
+ throw new IllegalArgumentException("Buffer start or length out of bounds.");
+ }
+ }
+
private native boolean native_open(String deviceName, FileDescriptor pfd);
private native void native_close();
private native int native_get_fd();
@@ -175,8 +235,9 @@
private native boolean native_claim_interface(int interfaceID, boolean force);
private native boolean native_release_interface(int interfaceID);
private native int native_control_request(int requestType, int request, int value,
- int index, byte[] buffer, int length, int timeout);
- private native int native_bulk_request(int endpoint, byte[] buffer, int length, int timeout);
+ int index, byte[] buffer, int start, int length, int timeout);
+ private native int native_bulk_request(int endpoint, byte[] buffer,
+ int start, int length, int timeout);
private native UsbRequest native_request_wait();
private native String native_get_serial();
}
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
index a554611..1165281 100644
--- a/core/java/android/net/BaseNetworkStateTracker.java
+++ b/core/java/android/net/BaseNetworkStateTracker.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.os.Handler;
+import android.os.Messenger;
import com.android.internal.util.Preconditions;
@@ -165,4 +166,9 @@
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
+
+ @Override
+ public void supplyMessenger(Messenger messenger) {
+ // not supported on this network
+ }
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3a04c27..4e4980d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
+import android.os.Messenger;
import android.os.RemoteException;
import android.provider.Settings;
@@ -1280,4 +1281,17 @@
}
}
+ /**
+ * Supply the backend messenger for a network tracker
+ *
+ * @param type NetworkType to set
+ * @param messenger {@link Messenger}
+ * {@hide}
+ */
+ public void supplyMessenger(int networkType, Messenger messenger) {
+ try {
+ mService.supplyMessenger(networkType, messenger);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index db8f0bc..15a81f3 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.os.Handler;
import android.os.Message;
+import android.os.Messenger;
import android.util.Slog;
/**
@@ -213,6 +214,11 @@
mLinkProperties.removeStackedLink(link);
}
+ @Override
+ public void supplyMessenger(Messenger messenger) {
+ // not supported on this network
+ }
+
static private void log(String s) {
Slog.d(TAG, s);
}
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index b744a47..27d5a58 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -22,6 +22,7 @@
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.util.Log;
@@ -417,4 +418,9 @@
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
+
+ @Override
+ public void supplyMessenger(Messenger messenger) {
+ // not supported on this network
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 056fa03..9e9b43d 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -22,6 +22,7 @@
import android.net.NetworkState;
import android.net.ProxyProperties;
import android.os.IBinder;
+import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import com.android.internal.net.LegacyVpnInfo;
@@ -126,4 +127,6 @@
boolean updateLockdownVpn();
void captivePortalCheckComplete(in NetworkInfo info);
+
+ void supplyMessenger(int networkType, in Messenger messenger);
}
diff --git a/core/java/android/net/LinkCapabilities.java b/core/java/android/net/LinkCapabilities.java
index eb9166f..fb444ea 100644
--- a/core/java/android/net/LinkCapabilities.java
+++ b/core/java/android/net/LinkCapabilities.java
@@ -314,8 +314,8 @@
sb.append(":\"");
sb.append(entry.getValue());
sb.append("\"");
- return mCapabilities.toString();
}
+ sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index eedc372..52b238f 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -290,7 +290,7 @@
}
stacked += "] ";
}
- return ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked;
+ return "{" + ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked + "}";
}
/**
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index faf739b..e85dbcd 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -74,7 +74,6 @@
private Handler mHandler;
private AsyncChannel mDataConnectionTrackerAc;
- private Messenger mMessenger;
/**
* Create a new MobileDataStateTracker
@@ -103,7 +102,6 @@
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
- filter.addAction(DctConstants.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
mContext.registerReceiver(new MobileDataStateReceiver(), filter);
mMobileDataState = PhoneConstants.DataState.DISCONNECTED;
@@ -285,13 +283,6 @@
" broadcast" + reason == null ? "" : "(" + reason + ")");
}
setDetailedState(DetailedState.FAILED, reason, apnName);
- } else if (intent.getAction().equals(DctConstants
- .ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
- if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
- mMessenger =
- intent.getParcelableExtra(DctConstants.EXTRA_MESSENGER);
- AsyncChannel ac = new AsyncChannel();
- ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
} else {
if (DBG) log("Broadcast received: ignore " + intent.getAction());
}
@@ -613,6 +604,12 @@
return new LinkCapabilities(mLinkCapabilities);
}
+ public void supplyMessenger(Messenger messenger) {
+ if (VDBG) log(mApnType + " got supplyMessenger");
+ AsyncChannel ac = new AsyncChannel();
+ ac.connect(mContext, MobileDataStateTracker.this.mHandler, messenger);
+ }
+
private void log(String s) {
Slog.d(TAG, mApnType + ": " + s);
}
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index b22159c..cf77a1c 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -18,6 +18,9 @@
import android.content.Context;
import android.os.Handler;
+import android.os.Messenger;
+
+import static com.android.internal.util.Protocol.BASE_NETWORK_STATE_TRACKER;
/**
* Interface provides the {@link com.android.server.ConnectivityService}
@@ -48,25 +51,38 @@
* msg.what = EVENT_STATE_CHANGED
* msg.obj = NetworkInfo object
*/
- public static final int EVENT_STATE_CHANGED = 1;
+ public static final int EVENT_STATE_CHANGED = BASE_NETWORK_STATE_TRACKER;
/**
* msg.what = EVENT_CONFIGURATION_CHANGED
* msg.obj = NetworkInfo object
*/
- public static final int EVENT_CONFIGURATION_CHANGED = 3;
+ public static final int EVENT_CONFIGURATION_CHANGED = BASE_NETWORK_STATE_TRACKER + 1;
/**
* msg.what = EVENT_RESTORE_DEFAULT_NETWORK
* msg.obj = FeatureUser object
*/
- public static final int EVENT_RESTORE_DEFAULT_NETWORK = 6;
+ public static final int EVENT_RESTORE_DEFAULT_NETWORK = BASE_NETWORK_STATE_TRACKER + 2;
/**
* msg.what = EVENT_NETWORK_SUBTYPE_CHANGED
* msg.obj = NetworkInfo object
*/
- public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 7;
+ public static final int EVENT_NETWORK_SUBTYPE_CHANGED = BASE_NETWORK_STATE_TRACKER + 3;
+
+ /**
+ * msg.what = EVENT_NETWORK_CONNECTED
+ * msg.obj = LinkProperties object
+ */
+ public static final int EVENT_NETWORK_CONNECTED = BASE_NETWORK_STATE_TRACKER + 4;
+
+ /**
+ * msg.what = EVENT_NETWORK_CONNECTION_DISCONNECTED
+ * msg.obj = LinkProperties object, same iface name
+ */
+ public static final int EVENT_NETWORK_DISCONNECTED = BASE_NETWORK_STATE_TRACKER + 5;
+
/**
* -------------------------------------------------------------
@@ -207,4 +223,10 @@
* Informs the state tracker that a stacked interface has been removed.
**/
public void removeStackedLink(LinkProperties link);
+
+ /*
+ * Called once to setup async channel between this and
+ * the underlying network specific code.
+ */
+ public void supplyMessenger(Messenger messenger);
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 4b83611..45524c8 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -152,16 +152,6 @@
boolean isTetheringStarted();
/**
- * Start bluetooth reverse tethering services
- */
- void startReverseTethering(in String iface);
-
- /**
- * Stop currently running bluetooth reserse tethering services
- */
- void stopReverseTethering();
-
- /**
* Tethers the specified interface
*/
void tetherInterface(String iface);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 622308f..1ba16bd 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -86,8 +86,42 @@
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
+
public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
+ /**
+ * Key for user restrictions. Specifies if a user is disallowed from enabling the
+ * "Unknown Sources" setting, that allows installation of apps from unknown sources.
+ * The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
+
+ /**
+ * Key for user restrictions. Specifies if a user is disallowed from configuring bluetooth.
+ * The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
+
+
+ /**
+ * Key for user restrictions. Specifies if a user is disallowed from transferring files over
+ * USB. The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
+
+
/** @hide */
public UserManager(Context context, IUserManager service) {
mService = service;
@@ -130,7 +164,7 @@
/**
* Used to determine whether the user making this call is subject to
* teleportations.
- * @return whether the user making this call is a goat
+ * @return whether the user making this call is a goat
*/
public boolean isUserAGoat() {
return false;
@@ -272,6 +306,16 @@
}
/**
+ * @hide
+ * Returns whether the current user has been disallowed from performing certain actions
+ * or setting certain settings.
+ * @param restrictionKey the string key representing the restriction
+ */
+ public boolean hasUserRestriction(String restrictionKey) {
+ return getUserRestrictions().getBoolean(restrictionKey, false);
+ }
+
+ /**
* Return the serial number for a user. This is a device-unique
* number assigned to that user; if the user is deleted and then a new
* user created, the new users will not be given the same serial number.
@@ -465,7 +509,7 @@
* Returns the maximum number of users that can be created on this device. A return value
* of 1 means that it is a single user device.
* @hide
- * @return a value greater than or equal to 1
+ * @return a value greater than or equal to 1
*/
public static int getMaxSupportedUsers() {
// Don't allow multiple users on certain builds
@@ -508,13 +552,6 @@
return -1;
}
- /**
- * Returns whether the current user is allowed to toggle location sharing settings.
- * @hide
- */
- public boolean isLocationSharingToggleAllowed() {
- return !getUserRestrictions().getBoolean(DISALLOW_SHARE_LOCATION, false);
- }
/**
* @hide
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 90bcf1c..66083c8 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1359,7 +1359,7 @@
* status definitions. Automatically computed as the highest presence of all
* constituent raw contacts. The provider may choose not to store this value
* in persistent storage. The expectation is that presence status will be
- * updated on a regular basic.</td>
+ * updated on a regular basis.</td>
* </tr>
* <tr>
* <td>String</td>
@@ -4181,7 +4181,7 @@
* all IM rows. See {@link StatusUpdates} for individual status definitions.
* The provider may choose not to store this value
* in persistent storage. The expectation is that presence status will be
- * updated on a regular basic.
+ * updated on a regular basis.
* </td>
* </tr>
* <tr>
diff --git a/core/java/android/util/AttributeSet.java b/core/java/android/util/AttributeSet.java
index 470526c..74942ba 100644
--- a/core/java/android/util/AttributeSet.java
+++ b/core/java/android/util/AttributeSet.java
@@ -151,7 +151,7 @@
* Return the value of 'attribute' as a resource identifier.
*
* <p>Note that this is different than {@link #getAttributeNameResource}
- * in that it returns a the value contained in this attribute as a
+ * in that it returns the value contained in this attribute as a
* resource identifier (i.e., a value originally of the form
* "@package:type/resource"); the other method returns a resource
* identifier that identifies the name of the attribute.
@@ -230,7 +230,7 @@
* Return the value of attribute at 'index' as a resource identifier.
*
* <p>Note that this is different than {@link #getAttributeNameResource}
- * in that it returns a the value contained in this attribute as a
+ * in that it returns the value contained in this attribute as a
* resource identifier (i.e., a value originally of the form
* "@package:type/resource"); the other method returns a resource
* identifier that identifies the name of the attribute.
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index e711b94..9c00b7f 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -468,7 +468,8 @@
// Force reloading the image resource
sc.icon.setImageDrawable(null);
sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);
- if (sc.streamType == AudioManager.STREAM_RING &&
+ if (((sc.streamType == AudioManager.STREAM_RING) ||
+ (sc.streamType == AudioManager.STREAM_NOTIFICATION)) &&
mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {
sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate);
}
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 91b109e..b380403 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -52,5 +52,6 @@
public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000;
public static final int BASE_DNS_PINGER = 0x00050000;
public static final int BASE_NSD_MANAGER = 0x00060000;
+ public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000;
//TODO: define all used protocols
}
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index 923781e..cea5bbf 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -142,7 +142,7 @@
static jint
android_hardware_UsbDeviceConnection_control_request(JNIEnv *env, jobject thiz,
jint requestType, jint request, jint value, jint index,
- jbyteArray buffer, jint length, jint timeout)
+ jbyteArray buffer, jint start, jint length, jint timeout)
{
struct usb_device* device = get_device_from_object(env, thiz);
if (!device) {
@@ -152,25 +152,22 @@
jbyte* bufferBytes = NULL;
if (buffer) {
- if (env->GetArrayLength(buffer) < length) {
- jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
- return -1;
- }
- bufferBytes = env->GetByteArrayElements(buffer, 0);
+ bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL);
}
jint result = usb_device_control_transfer(device, requestType, request,
- value, index, bufferBytes, length, timeout);
+ value, index, bufferBytes + start, length, timeout);
- if (bufferBytes)
- env->ReleaseByteArrayElements(buffer, bufferBytes, 0);
+ if (bufferBytes) {
+ env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0);
+ }
return result;
}
static jint
android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz,
- jint endpoint, jbyteArray buffer, jint length, jint timeout)
+ jint endpoint, jbyteArray buffer, jint start, jint length, jint timeout)
{
struct usb_device* device = get_device_from_object(env, thiz);
if (!device) {
@@ -180,17 +177,14 @@
jbyte* bufferBytes = NULL;
if (buffer) {
- if (env->GetArrayLength(buffer) < length) {
- jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
- return -1;
- }
- bufferBytes = env->GetByteArrayElements(buffer, 0);
+ bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL);
}
- jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout);
+ jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes + start, length, timeout);
- if (bufferBytes)
- env->ReleaseByteArrayElements(buffer, bufferBytes, 0);
+ if (bufferBytes) {
+ env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0);
+ }
return result;
}
@@ -235,9 +229,9 @@
{"native_get_desc", "()[B", (void *)android_hardware_UsbDeviceConnection_get_desc},
{"native_claim_interface", "(IZ)Z",(void *)android_hardware_UsbDeviceConnection_claim_interface},
{"native_release_interface","(I)Z", (void *)android_hardware_UsbDeviceConnection_release_interface},
- {"native_control_request", "(IIII[BII)I",
+ {"native_control_request", "(IIII[BIII)I",
(void *)android_hardware_UsbDeviceConnection_control_request},
- {"native_bulk_request", "(I[BII)I",
+ {"native_bulk_request", "(I[BIII)I",
(void *)android_hardware_UsbDeviceConnection_bulk_request},
{"native_request_wait", "()Landroid/hardware/usb/UsbRequest;",
(void *)android_hardware_UsbDeviceConnection_request_wait},
diff --git a/core/res/res/values-mcc286/config.xml b/core/res/res/values-mcc286/config.xml
old mode 100755
new mode 100644
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5282df3..8c7a374 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2092,11 +2092,11 @@
<!-- Don't use a layer. -->
<enum name="none" value="0" />
<!-- Use a software layer. Refer to
- {@link android.view.View#setLayerType(int, android.graphics.Paint) for
+ {@link android.view.View#setLayerType(int, android.graphics.Paint)} for
more information. -->
<enum name="software" value="1" />
<!-- Use a hardware layer. Refer to
- {@link android.view.View#setLayerType(int, android.graphics.Paint) for
+ {@link android.view.View#setLayerType(int, android.graphics.Paint)} for
more information. -->
<enum name="hardware" value="2" />
</attr>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 2e4d053..0afe4c1 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -889,6 +889,11 @@
<!-- Declare that your application will be able to deal with RTL (right to left) layouts.
If set to false (default value), your application will not care about RTL layouts. -->
<attr name="supportsRtl" format="boolean" />
+ <!-- Declare that this application requires access to restricted accounts of a certain
+ type. The default value is null and restricted accounts won\'t be visible to this
+ application. The type should correspond to the account authenticator type, such as
+ "com.google" -->
+ <attr name="restrictedAccountType" format="string"/>
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 489a947..42d692f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2041,6 +2041,7 @@
<public type="attr" name="indicatorEnd" />
<public type="attr" name="childIndicatorStart" />
<public type="attr" name="childIndicatorEnd" />
+ <public type="attr" name="restrictedAccountType" />
<public type="style" name="Theme.NoTitleBar.Overscan" />
<public type="style" name="Theme.Light.NoTitleBar.Overscan" />
diff --git a/core/res/res/xml/kg_password_kbd_numeric.xml b/core/res/res/xml/kg_password_kbd_numeric.xml
old mode 100755
new mode 100644
diff --git a/docs/html/google/play/billing/v2/billing_integrate.jd b/docs/html/google/play/billing/v2/billing_integrate.jd
old mode 100755
new mode 100644
diff --git a/docs/html/images/ui/notifications/custom_message.png b/docs/html/images/ui/notifications/custom_message.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/images/ui/notifications/notifications_window.png b/docs/html/images/ui/notifications/notifications_window.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/images/ui/notifications/status_bar.png b/docs/html/images/ui/notifications/status_bar.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.mp4 b/docs/html/training/animation/anim_card_flip.mp4
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.ogv b/docs/html/training/animation/anim_card_flip.ogv
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.webm b/docs/html/training/animation/anim_card_flip.webm
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.mp4 b/docs/html/training/animation/anim_screenslide.mp4
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.ogv b/docs/html/training/animation/anim_screenslide.ogv
old mode 100755
new mode 100644
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.webm b/docs/html/training/animation/anim_screenslide.webm
old mode 100755
new mode 100644
Binary files differ
diff --git a/graphics/java/android/graphics/DashPathEffect.java b/graphics/java/android/graphics/DashPathEffect.java
index 4f16dc4..2bdecce 100644
--- a/graphics/java/android/graphics/DashPathEffect.java
+++ b/graphics/java/android/graphics/DashPathEffect.java
@@ -26,7 +26,7 @@
* controls the length of the dashes. The paint's strokeWidth controls the
* thickness of the dashes.
* Note: this patheffect only affects drawing with the paint's style is set
- * to STROKE or STROKE_AND_FILL. It is ignored if the drawing is done with
+ * to STROKE or FILL_AND_STROKE. It is ignored if the drawing is done with
* style == FILL.
* @param intervals array of ON and OFF distances
* @param phase offset into the intervals array
diff --git a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
index 79a7630..83faf35 100644
--- a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
@@ -28,10 +28,28 @@
import javax.security.auth.x500.X500Principal;
/**
- * This provides the required parameters needed for initializing the KeyPair
- * generator that works with
- * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore
- * facility</a>.
+ * This provides the required parameters needed for initializing the
+ * {@code KeyPairGenerator} that works with <a href="{@docRoot}
+ * guide/topics/security/keystore.html">Android KeyStore facility</a>. The
+ * Android KeyStore facility is accessed through a
+ * {@link java.security.KeyPairGenerator} API using the
+ * {@code AndroidKeyPairGenerator} provider. The {@code context} passed in may
+ * be used to pop up some UI to ask the user to unlock or initialize the Android
+ * keystore facility.
+ * <p>
+ * After generation, the {@code keyStoreAlias} is used with the
+ * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
+ * interface to retrieve the {@link PrivateKey} and its associated
+ * {@link Certificate} chain.
+ * <p>
+ * The KeyPair generator will create a self-signed certificate with the subject
+ * as its X.509v3 Subject Distinguished Name and as its X.509v3 Issuer
+ * Distinguished Name along with the other parameters specified with the
+ * {@link Builder}.
+ * <p>
+ * The self-signed certificate may be replaced at a later time by a certificate
+ * signed by a real Certificate Authority.
+ *
* @hide
*/
public class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
@@ -74,6 +92,7 @@
* period
* @throws IllegalArgumentException when any argument is {@code null} or
* {@code endDate} is before {@code startDate}.
+ * @hide should be built with AndroidKeyPairGeneratorSpecBuilder
*/
public AndroidKeyPairGeneratorSpec(Context context, String keyStoreAlias,
X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate) {
@@ -142,4 +161,121 @@
Date getEndDate() {
return mEndDate;
}
+
+ /**
+ * Builder class for {@link AndroidKeyPairGeneratorSpec} objects.
+ * <p>
+ * This will build a parameter spec for use with the <a href="{@docRoot}
+ * guide/topics/security/keystore.html">Android KeyStore facility</a>.
+ * <p>
+ * The required fields must be filled in with the builder.
+ * <p>
+ * Example:
+ *
+ * <pre class="prettyprint">
+ * Calendar start = new Calendar();
+ * Calendar end = new Calendar();
+ * end.add(1, Calendar.YEAR);
+ *
+ * AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec.Builder(mContext)
+ * .setAlias("myKey")
+ * .setSubject(new X500Principal("CN=myKey"))
+ * .setSerial(BigInteger.valueOf(1337))
+ * .setStartDate(start.getTime())
+ * .setEndDate(end.getTime())
+ * .build();
+ * </pre>
+ */
+ public static class Builder {
+ private final Context mContext;
+
+ private String mKeystoreAlias;
+
+ private X500Principal mSubjectDN;
+
+ private BigInteger mSerialNumber;
+
+ private Date mStartDate;
+
+ private Date mEndDate;
+
+ public Builder(Context context) {
+ if (context == null) {
+ throw new NullPointerException("context == null");
+ }
+ mContext = context;
+ }
+
+ /**
+ * Sets the alias to be used to retrieve the key later from a
+ * {@link java.security.KeyStore} instance using the
+ * {@code AndroidKeyStore} provider.
+ */
+ public Builder setAlias(String alias) {
+ if (alias == null) {
+ throw new NullPointerException("alias == null");
+ }
+ mKeystoreAlias = alias;
+ return this;
+ }
+
+ /**
+ * Sets the subject used for the self-signed certificate of the
+ * generated key pair.
+ */
+ public Builder setSubject(X500Principal subject) {
+ if (subject == null) {
+ throw new NullPointerException("subject == null");
+ }
+ mSubjectDN = subject;
+ return this;
+ }
+
+ /**
+ * Sets the serial number used for the self-signed certificate of the
+ * generated key pair.
+ */
+ public Builder setSerialNumber(BigInteger serialNumber) {
+ if (serialNumber == null) {
+ throw new NullPointerException("serialNumber == null");
+ }
+ mSerialNumber = serialNumber;
+ return this;
+ }
+
+ /**
+ * Sets the start of the validity period for the self-signed certificate
+ * of the generated key pair.
+ */
+ public Builder setStartDate(Date startDate) {
+ if (startDate == null) {
+ throw new NullPointerException("startDate == null");
+ }
+ mStartDate = startDate;
+ return this;
+ }
+
+ /**
+ * Sets the end of the validity period for the self-signed certificate
+ * of the generated key pair.
+ */
+ public Builder setEndDate(Date endDate) {
+ if (endDate == null) {
+ throw new NullPointerException("endDate == null");
+ }
+ mEndDate = endDate;
+ return this;
+ }
+
+ /**
+ * Builds the instance of the {@code AndroidKeyPairGeneratorSpec}.
+ *
+ * @throws IllegalArgumentException if a required field is missing
+ * @return built instance of {@code AndroidKeyPairGeneratorSpec}
+ */
+ public AndroidKeyPairGeneratorSpec build() {
+ return new AndroidKeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN,
+ mSerialNumber, mStartDate, mEndDate);
+ }
+ }
}
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index d8109ce..166849d 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -49,6 +49,8 @@
public static final String INSTALL_ACTION = "android.credentials.INSTALL";
+ public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER";
+
public static final String UNLOCK_ACTION = "com.android.credentials.UNLOCK";
/** Key prefix for CA certificates. */
@@ -83,6 +85,12 @@
public static final String EXTENSION_PFX = ".pfx";
/**
+ * Intent extra: install the certificate bundle as this UID instead of
+ * system.
+ */
+ public static final String EXTRA_INSTALL_AS_UID = "install_as_uid";
+
+ /**
* Intent extra: name for the user's private key.
*/
public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
index e6a3750..3d275cd 100644
--- a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
@@ -53,6 +53,26 @@
assertEquals("endDate should be the one specified", NOW_PLUS_10_YEARS, spec.getEndDate());
}
+ public void testBuilder_Success() throws Exception {
+ AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec.Builder(getContext())
+ .setAlias(TEST_ALIAS_1)
+ .setSubject(TEST_DN_1)
+ .setSerialNumber(SERIAL_1)
+ .setStartDate(NOW)
+ .setEndDate(NOW_PLUS_10_YEARS)
+ .build();
+
+ assertEquals("Context should be the one specified", getContext(), spec.getContext());
+
+ assertEquals("Alias should be the one specified", TEST_ALIAS_1, spec.getKeystoreAlias());
+
+ assertEquals("subjectDN should be the one specified", TEST_DN_1, spec.getSubjectDN());
+
+ assertEquals("startDate should be the one specified", NOW, spec.getStartDate());
+
+ assertEquals("endDate should be the one specified", NOW_PLUS_10_YEARS, spec.getEndDate());
+ }
+
public void testConstructor_NullContext_Failure() throws Exception {
try {
new AndroidKeyPairGeneratorSpec(null, TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 020c1e9..5ff92be 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -75,7 +75,7 @@
for (unsigned int i = 0; i < mOps.size(); i++) {
DrawOp* op = mOps[i];
- renderer.restoreDisplayState(op->state, kStateDeferFlag_Draw);
+ renderer.restoreDisplayState(op->state);
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
renderer.eventMark(op->name());
@@ -106,7 +106,7 @@
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
DEFER_LOGD("replaying state op batch %p", this);
- renderer.restoreDisplayState(mOp->state, 0);
+ renderer.restoreDisplayState(mOp->state);
// use invalid save count because it won't be used at flush time - RestoreToCountOp is the
// only one to use it, and we don't use that class at flush time, instead calling
@@ -117,12 +117,12 @@
}
private:
- StateOp* mOp;
+ const StateOp* mOp;
};
class RestoreToCountBatch : public DrawOpBatch {
public:
- RestoreToCountBatch(int restoreCount) : mRestoreCount(restoreCount) {}
+ RestoreToCountBatch(StateOp* op, int restoreCount) : mOp(op), mRestoreCount(restoreCount) {}
bool intersects(Rect& rect) {
// if something checks for intersection, it's trying to go backwards across a state op,
@@ -133,11 +133,15 @@
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount);
+
+ renderer.restoreDisplayState(mOp->state);
renderer.restoreToCount(mRestoreCount);
return DrawGlInfo::kStatusDone;
}
private:
+ // we use the state storage for the RestoreToCountOp, but don't replay the op itself
+ const StateOp* mOp;
/*
* The count used here represents the flush() time saveCount. This is as opposed to the
* DisplayList record time, or defer() time values (which are RestoreToCountOp's mCount, and
@@ -251,7 +255,8 @@
* Either will act as a barrier to draw operation reordering, as we want to play back layer
* save/restore and complex canvas modifications (including save/restore) in order.
*/
-void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount) {
+void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, StateOp* op,
+ int newSaveCount) {
DEFER_LOGD("%p addRestoreToCount %d", this, newSaveCount);
if (recordingComplexClip() && newSaveCount <= mComplexClipStackStart) {
@@ -265,7 +270,7 @@
while (!mSaveStack.isEmpty() && mSaveStack.top() >= newSaveCount) mSaveStack.pop();
- storeRestoreToCountBarrier(mSaveStack.size() + 1);
+ storeRestoreToCountBarrier(renderer, op, mSaveStack.size() + 1);
}
void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
@@ -338,11 +343,15 @@
resetBatchingState();
}
-void DeferredDisplayList::storeRestoreToCountBarrier(int newSaveCount) {
+void DeferredDisplayList::storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op,
+ int newSaveCount) {
DEFER_LOGD("%p adding restore to count %d barrier, pos %d",
this, newSaveCount, mBatches.size());
- mBatches.add(new RestoreToCountBatch(newSaveCount));
+ // store displayState for the restore operation, as it may be associated with a saveLayer that
+ // doesn't have kClip_SaveFlag set
+ renderer.storeDisplayState(op->state, getStateOpDeferFlags());
+ mBatches.add(new RestoreToCountBatch(op, newSaveCount));
resetBatchingState();
}
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 2afc8c1..3e450da 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -65,7 +65,7 @@
void addClip(OpenGLRenderer& renderer, ClipOp* op);
void addSaveLayer(OpenGLRenderer& renderer, SaveLayerOp* op, int newSaveCount);
void addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount);
- void addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount);
+ void addRestoreToCount(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
/**
* Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
@@ -81,7 +81,7 @@
void resetBatchingState();
void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
- void storeRestoreToCountBarrier(int newSaveCount);
+ void storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
bool recordingComplexClip() const { return mComplexClipStackStart >= 0; }
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 4f2db69..9c3d058 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -117,7 +117,7 @@
applyState(replayStruct.mRenderer, saveCount);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
};
class DrawOp : public DisplayListOp {
@@ -223,7 +223,7 @@
deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.save(mFlags);
}
@@ -251,11 +251,12 @@
: mCount(count) {}
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
- deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer, saveCount + mCount);
+ deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
+ this, saveCount + mCount);
deferStruct.mRenderer.restoreToCount(saveCount + mCount);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.restoreToCount(saveCount + mCount);
}
@@ -293,7 +294,7 @@
mAlpha, mMode, mFlags);
}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
}
@@ -330,7 +331,7 @@
TranslateOp(float dx, float dy)
: mDx(dx), mDy(dy) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.translate(mDx, mDy);
}
@@ -350,7 +351,7 @@
RotateOp(float degrees)
: mDegrees(degrees) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.rotate(mDegrees);
}
@@ -369,7 +370,7 @@
ScaleOp(float sx, float sy)
: mSx(sx), mSy(sy) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.scale(mSx, mSy);
}
@@ -389,7 +390,7 @@
SkewOp(float sx, float sy)
: mSx(sx), mSy(sy) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.skew(mSx, mSy);
}
@@ -409,7 +410,7 @@
SetMatrixOp(SkMatrix* matrix)
: mMatrix(matrix) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setMatrix(mMatrix);
}
@@ -428,7 +429,7 @@
ConcatMatrixOp(SkMatrix* matrix)
: mMatrix(matrix) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.concatMatrix(mMatrix);
}
@@ -471,7 +472,7 @@
ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
: ClipOp(op), mArea(left, top, right, bottom) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
}
@@ -500,7 +501,7 @@
ClipPathOp(SkPath* path, SkRegion::Op op)
: ClipOp(op), mPath(path) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.clipPath(mPath, mOp);
}
@@ -521,7 +522,7 @@
ClipRegionOp(SkRegion* region, SkRegion::Op op)
: ClipOp(op), mRegion(region) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.clipRegion(mRegion, mOp);
}
@@ -540,7 +541,7 @@
class ResetShaderOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetShader();
}
@@ -555,7 +556,7 @@
public:
SetupShaderOp(SkiaShader* shader)
: mShader(shader) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupShader(mShader);
}
@@ -571,7 +572,7 @@
class ResetColorFilterOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetColorFilter();
}
@@ -587,7 +588,7 @@
SetupColorFilterOp(SkiaColorFilter* colorFilter)
: mColorFilter(colorFilter) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupColorFilter(mColorFilter);
}
@@ -603,7 +604,7 @@
class ResetShadowOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetShadow();
}
@@ -619,7 +620,7 @@
SetupShadowOp(float radius, float dx, float dy, int color)
: mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupShadow(mRadius, mDx, mDy, mColor);
}
@@ -638,7 +639,7 @@
class ResetPaintFilterOp : public StateOp {
public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.resetPaintFilter();
}
@@ -654,7 +655,7 @@
SetupPaintFilterOp(int clearBits, int setBits)
: mClearBits(clearBits), mSetBits(setBits) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
+ virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
renderer.setupPaintFilter(mClearBits, mSetBits);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 07daa3b..0b8f7e6 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -248,9 +248,7 @@
}
status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) {
- mLayers.add(layer);
- mCaches.resourceCache.incrementRefcount(layer);
-
+ layer = refLayer(layer);
addDrawOp(new (alloc()) DrawLayerOp(layer, x, y));
return DrawGlInfo::kStatusDone;
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 50e552f..19f7eb6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -271,6 +271,12 @@
return copy;
}
+ inline Layer* refLayer(Layer* layer) {
+ mLayers.add(layer);
+ mCaches.resourceCache.incrementRefcount(layer);
+ return layer;
+ }
+
inline SkBitmap* refBitmap(SkBitmap* bitmap) {
// Note that this assumes the bitmap is immutable. There are cases this won't handle
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
old mode 100755
new mode 100644
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
old mode 100755
new mode 100644
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 2998535..0267a66 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -75,6 +75,13 @@
return true;
}
+ const uint32_t maxTextureSize = Caches::getInstance().maxTextureSize;
+ if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) {
+ ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
+ desiredWidth, desiredHeight, maxTextureSize, maxTextureSize);
+ return false;
+ }
+
uint32_t oldWidth = getWidth();
uint32_t oldHeight = getHeight();
@@ -161,7 +168,7 @@
}
void Layer::flush() {
- if (deferredList && !deferredList->isEmpty()) {
+ if (deferredList) {
renderer->setViewport(layer.getWidth(), layer.getHeight());
renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
!isBlend());
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index bb02286..8451048 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -222,6 +222,21 @@
return NULL;
}
+ // We first obtain a layer before comparing against the max texture size
+ // because layers are not allocated at the exact desired size. They are
+ // always created slighly larger to improve recycling
+ const uint32_t maxTextureSize = caches.maxTextureSize;
+ if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) {
+ ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
+ width, height, maxTextureSize, maxTextureSize);
+
+ // Creating a new layer always increment its refcount by 1, this allows
+ // us to destroy the layer object if one was created for us
+ Caches::getInstance().resourceCache.decrementRefcount(layer);
+
+ return NULL;
+ }
+
layer->setFbo(fbo);
layer->layer.set(0.0f, 0.0f, width, height);
layer->texCoords.set(0.0f, height / float(layer->getHeight()),
@@ -243,14 +258,11 @@
layer->setEmpty(false);
layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+ // This should only happen if we run out of memory
if (glGetError() != GL_NO_ERROR) {
- ALOGD("Could not allocate texture for layer (fbo=%d %dx%d)",
- fbo, width, height);
-
+ ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-
- Caches::getInstance().resourceCache.decrementRefcount(layer);
-
+ caches.resourceCache.decrementRefcount(layer);
return NULL;
}
}
@@ -272,7 +284,6 @@
layer->texCoords.set(0.0f, height / float(layer->getHeight()),
width / float(layer->getWidth()), 0.0f);
} else {
- Caches::getInstance().resourceCache.decrementRefcount(layer);
return false;
}
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2903bcd..aeabe366 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -696,7 +696,10 @@
}
if (restoreLayer) {
+ endMark(); // Savelayer
+ startMark("ComposeLayer");
composeLayer(current, previous);
+ endMark();
}
return restoreClip;
@@ -874,6 +877,7 @@
mSnapshot->flags |= Snapshot::kFlagIsLayer;
mSnapshot->layer = layer;
+ startMark("SaveLayer");
if (fboLayer) {
return createFboLayer(layer, bounds, clip, previousFbo);
} else {
@@ -1326,8 +1330,6 @@
} else {
state.mBounds.set(currentClip);
}
- state.mDrawModifiers = mDrawModifiers;
- state.mAlpha = mSnapshot->alpha;
}
if (stateDeferFlags & kStateDeferFlag_Clip) {
@@ -1336,18 +1338,18 @@
state.mClip.setEmpty();
}
- // transform always deferred
+ // Transform, drawModifiers, and alpha always deferred, since they are used by state operations
+ // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
state.mMatrix.load(currentMatrix);
+ state.mDrawModifiers = mDrawModifiers;
+ state.mAlpha = mSnapshot->alpha;
return false;
}
-void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags) {
+void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
currentTransform().load(state.mMatrix);
-
- if (stateDeferFlags & kStateDeferFlag_Draw) {
- mDrawModifiers = state.mDrawModifiers;
- mSnapshot->alpha = state.mAlpha;
- }
+ mDrawModifiers = state.mDrawModifiers;
+ mSnapshot->alpha = state.mAlpha;
if (!state.mClip.isEmpty()) {
mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b17bc3f..04a47fc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -278,7 +278,7 @@
SkPaint* filterPaint(SkPaint* paint);
bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
- void restoreDisplayState(const DeferredDisplayState& state, int stateDeferFlags);
+ void restoreDisplayState(const DeferredDisplayState& state);
const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 38cdb8a..cf48cdb 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1533,7 +1533,9 @@
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
// SCO connections not started by the application changing the mode
if (newModeOwnerPid != 0) {
- disconnectBluetoothSco(newModeOwnerPid);
+ final long ident = Binder.clearCallingIdentity();
+ disconnectBluetoothSco(newModeOwnerPid);
+ Binder.restoreCallingIdentity(ident);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 4a67997..a446e40 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -98,11 +98,11 @@
private void setGpsLocation(String value) {
UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (! um.isLocationSharingToggleAllowed()) {
+ if (um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) {
return;
}
final String GPS = LocationManager.GPS_PROVIDER;
- boolean enabled =
+ boolean enabled =
GPS.equals(value) ||
value.startsWith(GPS + ",") ||
value.endsWith("," + GPS) ||
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
old mode 100755
new mode 100644
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
old mode 100755
new mode 100644
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
old mode 100755
new mode 100644
index 33e712a..ea7b696
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothManager;
import android.bluetooth.IBluetoothManagerCallback;
@@ -87,6 +88,9 @@
// and Airplane mode will have higher priority.
private static final int BLUETOOTH_ON_AIRPLANE=2;
+ private static final int SERVICE_IBLUETOOTH = 1;
+ private static final int SERVICE_IBLUETOOTHGATT = 2;
+
private final Context mContext;
// Locks are not provided for mName and mAddress.
@@ -97,6 +101,7 @@
private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
private IBluetooth mBluetooth;
+ private IBluetoothGatt mBluetoothGatt;
private boolean mBinding;
private boolean mUnbinding;
// used inside handler thread
@@ -463,6 +468,11 @@
}
}
+ public IBluetoothGatt getBluetoothGatt() {
+ // sync protection
+ return mBluetoothGatt;
+ }
+
private void sendBluetoothStateCallback(boolean isUp) {
int n = mStateChangeCallbacks.beginBroadcast();
if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
@@ -575,16 +585,35 @@
}
public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService");
+ if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
+ // TBD if (className.getClassName().equals(IBluetooth.class.getName())) {
+ if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
+ msg.arg1 = SERVICE_IBLUETOOTH;
+ // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) {
+ } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
+ msg.arg1 = SERVICE_IBLUETOOTHGATT;
+ } else {
+ Log.e(TAG, "Unknown service connected: " + className.getClassName());
+ return;
+ }
msg.obj = service;
mHandler.sendMessage(msg);
}
public void onServiceDisconnected(ComponentName className) {
// Called if we unexpected disconnected.
- if (DBG) Log.d(TAG, "BluetoothServiceConnection: disconnected from AdapterService");
+ if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " +
+ className.getClassName());
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
+ if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
+ msg.arg1 = SERVICE_IBLUETOOTH;
+ } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
+ msg.arg1 = SERVICE_IBLUETOOTHGATT;
+ } else {
+ Log.e(TAG, "Unknown service disconnected: " + className.getClassName());
+ return;
+ }
mHandler.sendMessage(msg);
}
}
@@ -746,13 +775,18 @@
}
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
- if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
-
- //Remove timeout
- mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+ if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
IBinder service = (IBinder) msg.obj;
synchronized(mConnection) {
+ if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
+ mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
+ break;
+ } // else must be SERVICE_IBLUETOOTH
+
+ //Remove timeout
+ mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+
mBinding = false;
mBluetooth = IBluetooth.Stub.asInterface(service);
@@ -816,11 +850,19 @@
}
case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
{
- Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
+ Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1);
synchronized(mConnection) {
- // if service is unbinded already, do nothing and return
- if (mBluetooth == null) return;
- mBluetooth = null;
+ if (msg.arg1 == SERVICE_IBLUETOOTH) {
+ // if service is unbinded already, do nothing and return
+ if (mBluetooth == null) break;
+ mBluetooth = null;
+ } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
+ mBluetoothGatt = null;
+ break;
+ } else {
+ Log.e(TAG, "Bad msg.arg1: " + msg.arg1);
+ break;
+ }
}
if (mEnable) {
@@ -1048,10 +1090,19 @@
boolean isUp = (newState==BluetoothAdapter.STATE_ON);
sendBluetoothStateCallback(isUp);
- //If Bluetooth is off, send service down event to proxy objects, and unbind
- if (!isUp && canUnbindBluetoothService()) {
- sendBluetoothServiceDownCallback();
- unbindAndFinish();
+ if (isUp) {
+ // connect to GattService
+ Intent i = new Intent(IBluetoothGatt.class.getName());
+ if (!mContext.bindServiceAsUser(i, mConnection, Context.BIND_AUTO_CREATE,
+ UserHandle.CURRENT)) {
+ Log.e(TAG, "Fail to bind to: " + IBluetoothGatt.class.getName());
+ }
+ } else {
+ //If Bluetooth is off, send service down event to proxy objects, and unbind
+ if (!isUp && canUnbindBluetoothService()) {
+ sendBluetoothServiceDownCallback();
+ unbindAndFinish();
+ }
}
}
@@ -1081,9 +1132,9 @@
if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
} else if (off) {
if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
- } else {
+ } else {
if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
- }
+ }
} catch (RemoteException e) {
Log.e(TAG, "getState()", e);
break;
@@ -1091,9 +1142,9 @@
}
if (on || off) {
SystemClock.sleep(300);
- } else {
+ } else {
SystemClock.sleep(50);
- }
+ }
i++;
}
Log.e(TAG,"waitForOnOff time out");
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 9daf038..9e06db8 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -74,6 +74,7 @@
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
+import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
@@ -3228,7 +3229,7 @@
throwIfLockdownEnabled();
try {
int type = mActiveDefaultNetwork;
- if (ConnectivityManager.isNetworkTypeValid(type)) {
+ if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) {
mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
return true;
}
@@ -3433,4 +3434,12 @@
throw new IllegalStateException("Unavailable in lockdown mode");
}
}
+
+ public void supplyMessenger(int networkType, Messenger messenger) {
+ enforceConnectivityInternalPermission();
+
+ if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) {
+ mNetTrackers[networkType].supplyMessenger(messenger);
+ }
+ }
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 2210a18..d2acb40 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -839,33 +839,6 @@
return event.getMessage().endsWith("started");
}
- // TODO(BT) Remove
- @Override
- public void startReverseTethering(String iface) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- // cmd is "tether start first_start first_stop second_start second_stop ..."
- // an odd number of addrs will fail
- try {
- mConnector.execute("tether", "start-reverse", iface);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
- BluetoothTetheringDataTracker.getInstance().startReverseTether(iface);
-
- }
-
- // TODO(BT) Remove
- @Override
- public void stopReverseTethering() {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- try {
- mConnector.execute("tether", "stop-reverse");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
- BluetoothTetheringDataTracker.getInstance().stopReverseTether();
- }
-
@Override
public void tetherInterface(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java
index c4b98ad..03679a5 100644
--- a/services/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/java/com/android/server/accounts/AccountManagerService.java
@@ -906,6 +906,7 @@
}
}
+ @Override
public void invalidateAuthToken(String accountType, String authToken) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "invalidateAuthToken: accountType " + accountType
@@ -1351,7 +1352,7 @@
String subtitle = "";
if (index > 0) {
title = titleAndSubtitle.substring(0, index);
- subtitle = titleAndSubtitle.substring(index + 1);
+ subtitle = titleAndSubtitle.substring(index + 1);
}
UserHandle user = new UserHandle(userId);
n.setLatestEventInfo(mContext, title, subtitle,
@@ -1426,8 +1427,7 @@
checkManageAccountsPermission();
// Is user disallowed from modifying accounts?
- if (getUserManager().getUserRestrictions(Binder.getCallingUserHandle())
- .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
+ if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
try {
response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
"User is not allowed to add an account!");
@@ -2570,9 +2570,7 @@
private boolean canUserModifyAccounts(int callingUid) {
if (callingUid != android.os.Process.myUid()) {
- Bundle restrictions = getUserManager().getUserRestrictions(
- new UserHandle(UserHandle.getUserId(callingUid)));
- if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
+ if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
return false;
}
}
@@ -2710,7 +2708,7 @@
}
if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) {
String[] packages = mPackageManager.getPackagesForUid(callingUid);
- // If any of the packages includes a white listed package, return the full set,
+ // If any of the packages is a white listed package, return the full set,
// otherwise return non-shared accounts only.
// This might be a temporary way to specify a whitelist
String whiteList = mContext.getResources().getString(
@@ -2723,16 +2721,30 @@
ArrayList<Account> allowed = new ArrayList<Account>();
Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId);
if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered;
- for (Account account : unfiltered) {
- boolean found = false;
- for (Account shared : sharedAccounts) {
- if (shared.equals(account)) {
- found = true;
- break;
+ String requiredAccountType = "";
+ try {
+ for (String packageName : packages) {
+ PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+ if (pi != null && pi.restrictedAccountType != null) {
+ requiredAccountType = pi.restrictedAccountType;
}
}
- if (!found) {
+ } catch (NameNotFoundException nnfe) {
+ }
+ for (Account account : unfiltered) {
+ if (account.type.equals(requiredAccountType)) {
allowed.add(account);
+ } else {
+ boolean found = false;
+ for (Account shared : sharedAccounts) {
+ if (shared.equals(account)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ allowed.add(account);
+ }
}
}
Account[] filtered = new Account[allowed.size()];
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index 9e25e30..1a635a9 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -144,8 +144,8 @@
// These are the high-end OOM level limits. This is appropriate for a
// 1280x800 or larger screen with around 1GB RAM. Values are in KB.
private final long[] mOomMinFreeHigh = new long[] {
- 32768, 40960, 49152,
- 57344, 65536, 81920
+ 49152, 61440, 73728,
+ 86016, 98304, 122880
};
// The actual OOM killer memory levels we are using.
private final long[] mOomMinFree = new long[mOomAdj.length];
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
index 15d2a5a..4bbdb5e 100644
--- a/services/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -206,10 +206,10 @@
String tagName = parser.getName();
if ("seinfo".equals(tagName)) {
String seinfoValue = parser.getAttributeValue(null, "value");
- if (seinfoValue != null) {
+ if (validateValue(seinfoValue)) {
seinfo = seinfoValue;
} else {
- Slog.w(TAG, "<seinfo> without value at "
+ Slog.w(TAG, "<seinfo> without valid value at "
+ parser.getPositionDescription());
}
}
@@ -219,6 +219,28 @@
}
/**
+ * General validation routine for tag values.
+ * Returns a boolean indicating if the passed string
+ * contains only letters or underscores.
+ */
+ private static boolean validateValue(String name) {
+ if (name == null)
+ return false;
+
+ final int N = name.length();
+ if (N == 0)
+ return false;
+
+ for (int i = 0; i < N; i++) {
+ final char c = name.charAt(i);
+ if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c != '_')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Labels a package based on an seinfo tag from install policy.
* The label is attached to the ApplicationInfo instance of the package.
* @param PackageParser.Package object representing the package
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index e13a17b..70183df 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1372,6 +1372,7 @@
// userId - application-specific user id
// debugFlag - 0 or 1 if the package is debuggable.
// dataPath - path to package's data path
+ // seinfo - seinfo label for the app (assigned at install time)
//
// NOTE: We prefer not to expose all ApplicationInfo flags for now.
//
@@ -1385,6 +1386,8 @@
sb.append((int)ai.uid);
sb.append(isDebug ? " 1 " : " 0 ");
sb.append(dataPath);
+ sb.append(" ");
+ sb.append(ai.seinfo);
sb.append("\n");
str.write(sb.toString().getBytes());
}
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index fecc2df..01ea1a2 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -26,7 +26,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.RestrictionEntry;
-import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
@@ -619,6 +618,10 @@
writeBoolean(serializer, restrictions, UserManager.DISALLOW_INSTALL_APPS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNINSTALL_APPS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_SHARE_LOCATION);
+ writeBoolean(serializer, restrictions,
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER);
serializer.endTag(null, TAG_RESTRICTIONS);
}
serializer.endTag(null, TAG_USER);
@@ -735,6 +738,10 @@
readBoolean(parser, restrictions, UserManager.DISALLOW_INSTALL_APPS);
readBoolean(parser, restrictions, UserManager.DISALLOW_UNINSTALL_APPS);
readBoolean(parser, restrictions, UserManager.DISALLOW_SHARE_LOCATION);
+ readBoolean(parser, restrictions,
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER);
}
}
}
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index f9aaa17..9b5b312 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -34,6 +34,7 @@
import android.hardware.usb.UsbManager;
import android.os.Binder;
import android.os.Environment;
+import android.os.Process;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.Log;
@@ -853,21 +854,29 @@
public boolean hasPermission(UsbDevice device) {
synchronized (mLock) {
+ int uid = Binder.getCallingUid();
+ if (uid == Process.SYSTEM_UID) {
+ return true;
+ }
SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
if (uidList == null) {
return false;
}
- return uidList.get(Binder.getCallingUid());
+ return uidList.get(uid);
}
}
public boolean hasPermission(UsbAccessory accessory) {
synchronized (mLock) {
+ int uid = Binder.getCallingUid();
+ if (uid == Process.SYSTEM_UID) {
+ return true;
+ }
SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
if (uidList == null) {
return false;
}
- return uidList.get(Binder.getCallingUid());
+ return uidList.get(uid);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index c501553..a70ebf4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -111,9 +111,9 @@
private void writePackagesList() {
writeFile(new File(getContext().getFilesDir(), "system/packages.list"),
- ( "com.google.app1 11000 0 /data/data/com.google.app1"
- + "com.google.app2 11001 0 /data/data/com.google.app2"
- + "com.android.app3 11030 0 /data/data/com.android.app3")
+ ( "com.google.app1 11000 0 /data/data/com.google.app1 seinfo1"
+ + "com.google.app2 11001 0 /data/data/com.google.app2 seinfo2"
+ + "com.android.app3 11030 0 /data/data/com.android.app3 seinfo3")
.getBytes());
}
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index cacafd4..9d556c0 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -111,7 +111,4 @@
public static final int ENABLED = 1;
public static final String APN_TYPE_KEY = "apnType";
- public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER =
- "com.android.internal.telephony";
- public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 32cd2f6..f637e89 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -793,4 +793,14 @@
public boolean p2pServDiscCancelReq(String id) {
return doBooleanCommand("P2P_SERV_DISC_CANCEL_REQ " + id);
}
+
+ /* Set the current mode of miracast operation.
+ * 0 = disabled
+ * 1 = operating as source
+ * 2 = operating as sink
+ */
+ public void setMiracastMode(int mode) {
+ // Note: optional feature on the driver. It is ok for this to fail.
+ doBooleanCommand("DRIVER MIRACAST " + mode);
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 81d2e11..cf75381 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -27,6 +27,7 @@
import android.net.NetworkStateTracker;
import android.os.Handler;
import android.os.Message;
+import android.os.Messenger;
import android.util.Slog;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -262,4 +263,9 @@
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
+
+ @Override
+ public void supplyMessenger(Messenger messenger) {
+ // not supported on this network
+ }
}
diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
index 381a450..1c9c40d 100644
--- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
+++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -26,5 +26,6 @@
interface IWifiP2pManager
{
Messenger getMessenger();
+ void setMiracastMode(int mode);
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 2e80064..737ab91 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1258,6 +1258,21 @@
c.mAsyncChannel.sendMessage(REQUEST_PERSISTENT_GROUP_INFO, 0, c.putListener(listener));
}
+ /** @hide */
+ public static final int MIRACAST_DISABLED = 0;
+ /** @hide */
+ public static final int MIRACAST_SOURCE = 1;
+ /** @hide */
+ public static final int MIRACAST_SINK = 2;
+ /** Internal use only @hide */
+ public void setMiracastMode(int mode) {
+ try {
+ mService.setMiracastMode(mode);
+ } catch(RemoteException e) {
+ // ignore
+ }
+ }
+
/**
* Get a reference to WifiP2pService handler. This is used to establish
* an AsyncChannel communication with WifiService
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index e6a1df1..447ddb0 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -164,6 +164,8 @@
public static final int DISCONNECT_WIFI_REQUEST = BASE + 12;
public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13;
+ public static final int SET_MIRACAST_MODE = BASE + 14;
+
private final boolean mP2pSupported;
private WifiP2pDevice mThisDevice = new WifiP2pDevice();
@@ -310,6 +312,12 @@
"WifiP2pService");
}
+ private void enforceConnectivityInternalPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL,
+ "WifiP2pService");
+ }
+
/**
* Get a reference to handler. This is used by a client to establish
* an AsyncChannel communication with WifiP2pService
@@ -320,6 +328,20 @@
return new Messenger(mP2pStateMachine.getHandler());
}
+ /** This is used to provide information to drivers to optimize performance depending
+ * on the current mode of operation.
+ * 0 - disabled
+ * 1 - source operation
+ * 2 - sink operation
+ *
+ * As an example, the driver could reduce the channel dwell time during scanning
+ * when acting as a source or sink to minimize impact on miracast.
+ */
+ public void setMiracastMode(int mode) {
+ enforceConnectivityInternalPermission();
+ mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode);
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -572,6 +594,7 @@
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
case DhcpStateMachine.CMD_ON_QUIT:
case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
+ case SET_MIRACAST_MODE:
break;
case WifiStateMachine.CMD_ENABLE_P2P:
// Enable is lazy and has no response
@@ -878,7 +901,7 @@
sendPeersChangedBroadcast();
}
break;
- case WifiP2pManager.ADD_LOCAL_SERVICE:
+ case WifiP2pManager.ADD_LOCAL_SERVICE:
if (DBG) logd(getName() + " add service");
WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo)message.obj;
if (addLocalService(message.replyTo, servInfo)) {
@@ -916,7 +939,7 @@
clearServiceRequests(message.replyTo);
replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED);
break;
- case WifiMonitor.P2P_SERV_DISC_RESP_EVENT:
+ case WifiMonitor.P2P_SERV_DISC_RESP_EVENT:
if (DBG) logd(getName() + " receive service response");
List<WifiP2pServiceResponse> sdRespList =
(List<WifiP2pServiceResponse>) message.obj;
@@ -927,13 +950,16 @@
sendServiceResponse(resp);
}
break;
- case WifiP2pManager.DELETE_PERSISTENT_GROUP:
+ case WifiP2pManager.DELETE_PERSISTENT_GROUP:
if (DBG) logd(getName() + " delete persistent group");
mGroups.remove(message.arg1);
replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED);
break;
+ case SET_MIRACAST_MODE:
+ mWifiNative.setMiracastMode(message.arg1);
+ break;
default:
- return NOT_HANDLED;
+ return NOT_HANDLED;
}
return HANDLED;
}