diff options
-rw-r--r-- | core/java/android/app/WallpaperManager.java | 66 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 209 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothAdvScanData.java | 147 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothGatt.java | 73 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothGattServer.java | 2 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothGattService.java | 23 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothUuid.java | 16 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothGatt.aidl | 15 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothGattCallback.aidl | 1 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/ImageWallpaper.java | 117 |
10 files changed, 487 insertions, 182 deletions
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 4435032..e6e0f35 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -44,9 +44,7 @@ import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; -import android.util.DisplayMetrics; import android.util.Log; -import android.view.WindowManager; import android.view.WindowManagerGlobal; import java.io.BufferedInputStream; @@ -280,9 +278,8 @@ public class WallpaperManager { try { BitmapFactory.Options options = new BitmapFactory.Options(); - Bitmap bm = BitmapFactory.decodeFileDescriptor( + return BitmapFactory.decodeFileDescriptor( fd.getFileDescriptor(), null, options); - return generateBitmap(context, bm, width, height); } catch (OutOfMemoryError e) { Log.w(TAG, "Can't decode file", e); } finally { @@ -309,8 +306,7 @@ public class WallpaperManager { try { BitmapFactory.Options options = new BitmapFactory.Options(); - Bitmap bm = BitmapFactory.decodeStream(is, null, options); - return generateBitmap(context, bm, width, height); + return BitmapFactory.decodeStream(is, null, options); } catch (OutOfMemoryError e) { Log.w(TAG, "Can't decode stream", e); } finally { @@ -1015,62 +1011,4 @@ public class WallpaperManager { public void clear() throws IOException { setResource(com.android.internal.R.drawable.default_wallpaper); } - - static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) { - if (bm == null) { - return null; - } - - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - DisplayMetrics metrics = new DisplayMetrics(); - wm.getDefaultDisplay().getMetrics(metrics); - bm.setDensity(metrics.noncompatDensityDpi); - - if (width <= 0 || height <= 0 - || (bm.getWidth() == width && bm.getHeight() == height)) { - return bm; - } - - // This is the final bitmap we want to return. - try { - Bitmap newbm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - newbm.setDensity(metrics.noncompatDensityDpi); - - Canvas c = new Canvas(newbm); - Rect targetRect = new Rect(); - targetRect.right = bm.getWidth(); - targetRect.bottom = bm.getHeight(); - - int deltaw = width - targetRect.right; - int deltah = height - targetRect.bottom; - - if (deltaw > 0 || deltah > 0) { - // We need to scale up so it covers the entire area. - float scale; - if (deltaw > deltah) { - scale = width / (float)targetRect.right; - } else { - scale = height / (float)targetRect.bottom; - } - targetRect.right = (int)(targetRect.right*scale); - targetRect.bottom = (int)(targetRect.bottom*scale); - deltaw = width - targetRect.right; - deltah = height - targetRect.bottom; - } - - targetRect.offset(deltaw/2, deltah/2); - - Paint paint = new Paint(); - paint.setFilterBitmap(true); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); - c.drawBitmap(bm, null, targetRect, paint); - - bm.recycle(); - c.setBitmap(null); - return newbm; - } catch (OutOfMemoryError e) { - Log.w(TAG, "Can't generate default bitmap", e); - return bm; - } - } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 7ee2313..38a71aa 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -25,13 +25,14 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.util.Pair; + import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.HashMap; +import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -179,6 +180,43 @@ public final class BluetoothAdapter { "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION"; /** + * Activity Action: Show a system activity to request BLE advertising.<br> + * If the device is not doing BLE advertising, this activity will start BLE advertising for the + * device, otherwise it will continue BLE advertising using the current + * {@link BluetoothAdvScanData}. <br> + * Note this activity will also request the user to turn on Bluetooth if it's not currently + * enabled. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_START_ADVERTISING = + "android.bluetooth.adapter.action.START_ADVERTISING"; + + /** + * Activity Action: Stop the current BLE advertising. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_STOP_ADVERTISING = + "android.bluetooth.adapter.action.STOP_ADVERTISING"; + + /** + * Broadcast Action: Indicate BLE Advertising is started. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED = + "android.bluetooth.adapter.action.ADVERTISING_STARTED"; + + /** + * Broadcast Action: Indicated BLE Advertising is stopped. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED = + "android.bluetooth.adapter.action.ADVERTISING_STOPPED"; + + /** * Activity Action: Show a system activity that allows the user to turn on * Bluetooth. * <p>This system activity will return once Bluetooth has completed turning @@ -247,7 +285,6 @@ public final class BluetoothAdapter { */ public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; - /** * Broadcast Action: The local Bluetooth adapter has started the remote * device discovery process. @@ -361,6 +398,8 @@ public final class BluetoothAdapter { private IBluetooth mService; private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients; + private BluetoothAdvScanData mBluetoothAdvScanData = null; + private GattCallbackWrapper mAdvertisingCallback; /** * Get a handle to the default local Bluetooth adapter. @@ -434,6 +473,97 @@ public final class BluetoothAdapter { } /** + * Returns a {@link BluetoothAdvScanData} object representing advertising data. + * @hide + */ + public BluetoothAdvScanData getAdvScanData() { + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + if (iGatt == null) { + // BLE is not supported + Log.e(TAG, "failed to start, iGatt null"); + return null; + } + if (mBluetoothAdvScanData == null) { + mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD); + } + return mBluetoothAdvScanData; + } catch (RemoteException e) { + Log.e(TAG, "failed to get advScanData, error: " + e); + return null; + } + } + + + /** + * Start BLE advertising using current {@link BluetoothAdvScanData}. + * An app should start advertising by requesting + * {@link BluetoothAdapter#ACTION_START_ADVERTISING} instead of calling this method directly. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} + * + * @return true if BLE avertising succeeds, false otherwise. + * @hide + */ + public boolean startAdvertising() { + if (getState() != STATE_ON) return false; + + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + if (iGatt == null) { + // BLE is not supported. + return false; + } + // Restart/reset advertising packets if advertising is in progress. + if (isAdvertising()) { + // Invalid advertising callback. + if (mAdvertisingCallback == null || mAdvertisingCallback.mLeHandle == -1) { + Log.e(TAG, "failed to restart advertising, invalid callback"); + return false; + } + iGatt.startAdvertising(mAdvertisingCallback.mLeHandle); + return true; + } + UUID uuid = UUID.randomUUID(); + GattCallbackWrapper wrapper = + new GattCallbackWrapper(this, null, null, GattCallbackWrapper.CALLBACK_TYPE_ADV); + iGatt.registerClient(new ParcelUuid(uuid), wrapper); + mAdvertisingCallback = wrapper; + return true; + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** + * Stop BLE advertising. + * An app should stop advertising by requesting + * {@link BluetoothAdapter#ACTION_STOP_ADVERTISING} instead of calling this method directly. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} + * @return true if BLE advertising stops, false otherwise. + * @hide + */ + public boolean stopAdvertisting() { + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + if (iGatt == null) { + // BLE is not supported + return false; + } + if (mAdvertisingCallback == null) { + // no callback. + return false; + } + mAdvertisingCallback.stopAdvertising(); + mAdvertisingCallback = null; + return true; + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** * Return true if Bluetooth is currently enabled and ready for use. * <p>Equivalent to: * <code>getBluetoothState() == STATE_ON</code> @@ -845,6 +975,23 @@ public final class BluetoothAdapter { } /** + * Returns whether BLE is currently advertising. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * + * @hide + */ + public boolean isAdvertising() { + if (getState() != STATE_ON) return false; + try { + IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); + return iGatt.isAdvertising(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** * Return the set of {@link BluetoothDevice} objects that are bonded * (paired) to the local adapter. * <p>If Bluetooth state is not {@link #STATE_ON}, this API @@ -1542,8 +1689,12 @@ public final class BluetoothAdapter { private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub { private static final int LE_CALLBACK_REG_TIMEOUT = 2000; private static final int LE_CALLBACK_REG_WAIT_COUNT = 5; + private static final int CALLBACK_TYPE_SCAN = 0; + private static final int CALLBACK_TYPE_ADV = 1; private final LeScanCallback mLeScanCb; + private int mCallbackType; + // mLeHandle 0: not registered // -1: scan stopped // >0: registered and scan started @@ -1557,6 +1708,16 @@ public final class BluetoothAdapter { mLeScanCb = leScanCb; mScanFilter = uuid; mLeHandle = 0; + mCallbackType = CALLBACK_TYPE_SCAN; + } + + public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb, + UUID[] uuid, int type) { + mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter); + mLeScanCb = leScanCb; + mScanFilter = uuid; + mLeHandle = 0; + mCallbackType = type; } public boolean scanStarted() { @@ -1579,6 +1740,30 @@ public final class BluetoothAdapter { return started; } + public void stopAdvertising() { + synchronized (this) { + if (mLeHandle <= 0) { + Log.e(TAG, "Error state, mLeHandle: " + mLeHandle); + return; + } + BluetoothAdapter adapter = mBluetoothAdapter.get(); + if (adapter != null) { + try { + IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt(); + iGatt.stopAdvertising(); + Log.d(TAG, "unregeistering client " + mLeHandle); + iGatt.unregisterClient(mLeHandle); + } catch (RemoteException e) { + Log.e(TAG, "Failed to stop advertising and unregister" + e); + } + } else { + Log.e(TAG, "stopAdvertising, BluetoothAdapter is null"); + } + mLeHandle = -1; + notifyAll(); + } + } + public void stopLeScan() { synchronized(this) { if (mLeHandle <= 0) { @@ -1620,14 +1805,18 @@ public final class BluetoothAdapter { BluetoothAdapter adapter = mBluetoothAdapter.get(); if (adapter != null) { iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - if (mScanFilter == null) { - iGatt.startScan(mLeHandle, false); + if (mCallbackType == CALLBACK_TYPE_ADV) { + iGatt.startAdvertising(mLeHandle); } else { - ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; - for(int i = 0; i != uuids.length; ++i) { - uuids[i] = new ParcelUuid(mScanFilter[i]); - } - iGatt.startScanWithUuids(mLeHandle, false, uuids); + if (mScanFilter == null) { + iGatt.startScan(mLeHandle, false); + } else { + ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; + for(int i = 0; i != uuids.length; ++i) { + uuids[i] = new ParcelUuid(mScanFilter[i]); + } + iGatt.startScanWithUuids(mLeHandle, false, uuids); + } } } else { Log.e(TAG, "onClientRegistered, BluetoothAdapter null"); @@ -1638,7 +1827,7 @@ public final class BluetoothAdapter { mLeHandle = -1; } if (mLeHandle == -1) { - // registration succeeded but start scan failed + // registration succeeded but start scan or advertise failed if (iGatt != null) { try { iGatt.unregisterClient(mLeHandle); diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java new file mode 100644 index 0000000..a97b0a8 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothAdvScanData.java @@ -0,0 +1,147 @@ +/* + * 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.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + +import java.util.Collections; +import java.util.List; + + +/** + * This class provides the public APIs to set advertising and scan response data when BLE device + * operates in peripheral mode. <br> + * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11 + * @hide + */ +public final class BluetoothAdvScanData { + + /** + * Available data types of {@link BluetoothAdvScanData}. + */ + public static final int AD = 0; // Advertising Data + public static final int SCAN_RESPONSE = 1; // Scan Response + public static final int EIR = 2; // Extended Inquiry Response + + private static final String TAG = "BluetoothAdvScanData"; + + /** + * Data type of BluetoothAdvScanData. + */ + private final int mDataType; + /** + * Bluetooth Gatt Service. + */ + private IBluetoothGatt mBluetoothGatt; + + /** + * @param mBluetoothGatt + * @param dataType + */ + public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) { + this.mBluetoothGatt = mBluetoothGatt; + this.mDataType = dataType; + } + + /** + * @return advertising data type. + */ + public int getDataType() { + return mDataType; + } + + /** + * Set manufactureCode and manufactureData. + * Returns true if manufacturer data is set, false if there is no enough room to set + * manufacturer data or the data is already set. + * @param manufacturerCode - unique identifier for the manufacturer + * @param manufacturerData - data associated with the specific manufacturer. + */ + public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) { + if (mDataType != AD) return false; + try { + return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData); + } catch (RemoteException e) { + return false; + } + } + + /** + * Set service data. Note the service data can only be set when the data type is {@code AD}; + * @param serviceData + */ + public boolean setServiceData(byte[] serviceData) { + + if (mDataType != AD) return false; + if (serviceData == null) return false; + try { + return mBluetoothGatt.setAdvServiceData(serviceData); + } catch (RemoteException e) { + return false; + } + } + + /** + * Returns an immutable list of service uuids that will be advertised. + */ + public List<ParcelUuid> getServiceUuids() { + try { + return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids()); + } catch (RemoteException e) { + return null; + } + } + + /** + * Returns manufacturer data. + */ + public byte[] getManufacturerData() { + if (mBluetoothGatt == null) return null; + try { + return mBluetoothGatt.getAdvManufacturerData(); + } catch (RemoteException e) { + return null; + } + } + + /** + * Returns service data. + */ + public byte[] getServiceData() { + if (mBluetoothGatt == null) return null; + try { + return mBluetoothGatt.getAdvServiceData(); + } catch (RemoteException e) { + return null; + } + } + + /** + * Remove manufacturer data based on given manufacturer code. + * @param manufacturerCode + */ + public void removeManufacturerCodeAndData(int manufacturerCode) { + if (mBluetoothGatt != null) { + try { + mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } + } +} diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index b6e1bb3..e3820a2 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -544,14 +544,6 @@ public final class BluetoothGatt implements BluetoothProfile { Log.w(TAG, "Unhandled exception in callback", ex); } } - - /** - * Listen command status callback - * @hide - */ - public void onListen(int status) { - if (DBG) Log.d(TAG, "onListen() - status=" + status); - } }; /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) { @@ -684,71 +676,6 @@ public final class BluetoothGatt implements BluetoothProfile { return true; } - /** - * Starts or stops sending of advertisement packages to listen for connection - * requests from a central devices. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * - * @param start Start or stop advertising - */ - /*package*/ void listen(boolean start) { - if (mContext == null || !mContext.getResources(). - getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) { - throw new UnsupportedOperationException("BluetoothGatt#listen is blocked"); - } - if (DBG) Log.d(TAG, "listen() - start: " + start); - if (mService == null || mClientIf == 0) return; - - try { - mService.clientListen(mClientIf, start); - } catch (RemoteException e) { - Log.e(TAG,"",e); - } - } - - /** - * Sets the advertising data contained in the adv. response packet. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * - * @param advData true to set adv. data, false to set scan response - * @param includeName Inlucde the name in the adv. response - * @param includeTxPower Include TX power value - * @param minInterval Minimum desired scan interval (optional) - * @param maxInterval Maximum desired scan interval (optional) - * @param appearance The appearance flags for the device (optional) - * @param manufacturerData Manufacturer specific data including company ID (optional) - */ - /*package*/ void setAdvData(boolean advData, boolean includeName, boolean includeTxPower, - Integer minInterval, Integer maxInterval, - Integer appearance, Byte[] manufacturerData) { - if (mContext == null || !mContext.getResources(). - getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) { - throw new UnsupportedOperationException("BluetoothGatt#setAdvData is blocked"); - } - if (DBG) Log.d(TAG, "setAdvData()"); - if (mService == null || mClientIf == 0) return; - - byte[] data = new byte[0]; - if (manufacturerData != null) { - data = new byte[manufacturerData.length]; - for(int i = 0; i != manufacturerData.length; ++i) { - data[i] = manufacturerData[i]; - } - } - - try { - mService.setAdvData(mClientIf, !advData, - includeName, includeTxPower, - minInterval != null ? minInterval : 0, - maxInterval != null ? maxInterval : 0, - appearance != null ? appearance : 0, data); - } catch (RemoteException e) { - Log.e(TAG,"",e); - } - } - /** * Disconnects an established connection, or cancels a connection attempt * currently in progress. diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index 09072f9..0c00c06 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -528,7 +528,7 @@ public final class BluetoothGattServer implements BluetoothProfile { try { mService.beginServiceDeclaration(mServerIf, service.getType(), service.getInstanceId(), service.getHandles(), - new ParcelUuid(service.getUuid())); + new ParcelUuid(service.getUuid()), service.isAdvertisePreferred()); List<BluetoothGattService> includedServices = service.getIncludedServices(); for (BluetoothGattService includedService : includedServices) { diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java index 1e66369..52bc0f7 100644 --- a/core/java/android/bluetooth/BluetoothGattService.java +++ b/core/java/android/bluetooth/BluetoothGattService.java @@ -15,8 +15,6 @@ */ package android.bluetooth; -import android.bluetooth.BluetoothDevice; - import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -82,6 +80,11 @@ public class BluetoothGattService { protected List<BluetoothGattService> mIncludedServices; /** + * Whether the service uuid should be advertised. + */ + private boolean mAdvertisePreferred; + + /** * Create a new BluetoothGattService. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * @@ -263,4 +266,20 @@ public class BluetoothGattService { } return null; } + + /** + * Returns whether the uuid of the service should be advertised. + * @hide + */ + public boolean isAdvertisePreferred() { + return mAdvertisePreferred; + } + + /** + * Set whether the service uuid should be advertised. + * @hide + */ + public void setAdvertisePreferred(boolean advertisePreferred) { + this.mAdvertisePreferred = advertisePreferred; + } } diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index abdf949..4b28516 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -73,6 +73,9 @@ public final class BluetoothUuid { public static final ParcelUuid MAS = ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); + public static final ParcelUuid BASE_UUID = + ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); + public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, @@ -211,4 +214,17 @@ public final class BluetoothUuid { long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32; return (int)value; } + + /** + * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. + * @param parcelUuid + * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. + */ + public static boolean isShortUuid(ParcelUuid parcelUuid) { + UUID uuid = parcelUuid.getUuid(); + if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { + return false; + } + return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); + } } diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index df393db..784cdcc 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -37,10 +37,15 @@ interface IBluetoothGatt { void unregisterClient(in int clientIf); void clientConnect(in int clientIf, in String address, in boolean isDirect); void clientDisconnect(in int clientIf, in String address); - void clientListen(in int clientIf, in boolean start); - void setAdvData(in int clientIf, in boolean setScanRsp, in boolean inclName, - in boolean inclTxPower, in int minInterval, in int maxInterval, - in int appearance, in byte[] manufacturerData); + void startAdvertising(in int appIf); + void stopAdvertising(); + boolean setAdvServiceData(in byte[] serviceData); + byte[] getAdvServiceData(); + boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData); + byte[] getAdvManufacturerData(); + List<ParcelUuid> getAdvServiceUuids(); + void removeAdvManufacturerCodeAndData(int manufacturerCode); + boolean isAdvertising(); void refreshDevice(in int clientIf, in String address); void discoverServices(in int clientIf, in String address); void readCharacteristic(in int clientIf, in String address, in int srvcType, @@ -75,7 +80,7 @@ interface IBluetoothGatt { void serverDisconnect(in int serverIf, in String address); void beginServiceDeclaration(in int serverIf, in int srvcType, in int srvcInstanceId, in int minHandles, - in ParcelUuid srvcId); + in ParcelUuid srvcId, boolean advertisePreferred); void addIncludedService(in int serverIf, in int srvcType, in int srvcInstanceId, in ParcelUuid srvcId); void addCharacteristic(in int serverIf, in ParcelUuid charId, diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl index 60c297b..e3563fc 100644 --- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl @@ -63,5 +63,4 @@ interface IBluetoothGattCallback { in int charInstId, in ParcelUuid charUuid, in byte[] value); void onReadRemoteRssi(in String address, in int rssi, in int status); - void onListen(in int status); } diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index c7f4828..74483cc 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -27,13 +27,16 @@ import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Point; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Region.Op; import android.opengl.GLUtils; import android.os.SystemProperties; import android.renderscript.Matrix4f; import android.service.wallpaper.WallpaperService; import android.util.Log; +import android.view.Display; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.WindowManager; @@ -107,10 +110,12 @@ public class ImageWallpaper extends WallpaperService { private WallpaperObserver mReceiver; Bitmap mBackground; + int mBackgroundWidth = -1, mBackgroundHeight = -1; int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; int mLastRotation = -1; - float mXOffset; - float mYOffset; + float mXOffset = 0.5f; + float mYOffset = 0.5f; + float mScale = 1f; boolean mVisible = true; boolean mRedrawNeeded; @@ -155,6 +160,8 @@ public class ImageWallpaper extends WallpaperService { mLastSurfaceWidth = mLastSurfaceHeight = -1; mBackground = null; + mBackgroundWidth = -1; + mBackgroundHeight = -1; mRedrawNeeded = true; drawFrame(); } @@ -173,6 +180,8 @@ public class ImageWallpaper extends WallpaperService { } mBackground.recycle(); mBackground = null; + mBackgroundWidth = -1; + mBackgroundHeight = -1; mWallpaperManager.forgetLoadedWallpaper(); } } @@ -204,21 +213,40 @@ public class ImageWallpaper extends WallpaperService { } } - @Override - public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) { - super.onDesiredSizeChanged(desiredWidth, desiredHeight); - SurfaceHolder surfaceHolder = getSurfaceHolder(); - if (surfaceHolder != null) { - updateSurfaceSize(surfaceHolder); + void updateSurfaceSize(SurfaceHolder surfaceHolder) { + Point p = getDefaultDisplaySize(); + + // Load background image dimensions, if we haven't saved them yet + if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) { + // Need to load the image to get dimensions + mWallpaperManager.forgetLoadedWallpaper(); + updateWallpaperLocked(); + if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) { + // Default to the display size if we can't find the dimensions + mBackgroundWidth = p.x; + mBackgroundHeight = p.y; + } + } + + // Force the wallpaper to cover the screen in both dimensions + int surfaceWidth = Math.max(p.x, mBackgroundWidth); + int surfaceHeight = Math.max(p.y, mBackgroundHeight); + + // If the surface dimensions haven't changed, then just return + final Rect frame = surfaceHolder.getSurfaceFrame(); + if (frame != null) { + final int dw = frame.width(); + final int dh = frame.height(); + if (surfaceWidth == dw && surfaceHeight == dh) { + return; + } } - } - void updateSurfaceSize(SurfaceHolder surfaceHolder) { if (FIXED_SIZED_SURFACE) { // Used a fixed size surface, because we are special. We can do // this because we know the current design of window animations doesn't // cause this to break. - surfaceHolder.setFixedSize(getDesiredMinimumWidth(), getDesiredMinimumHeight()); + surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight); } else { surfaceHolder.setSizeFromLayout(); } @@ -298,13 +326,30 @@ public class ImageWallpaper extends WallpaperService { drawFrame(); } + private Point getDefaultDisplaySize() { + Point p = new Point(); + Context c = ImageWallpaper.this.getApplicationContext(); + WindowManager wm = (WindowManager)c.getSystemService(Context.WINDOW_SERVICE); + Display d = wm.getDefaultDisplay(); + d.getRealSize(p); + return p; + } + void drawFrame() { + int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)). + getDefaultDisplay().getRotation(); + + // Sometimes a wallpaper is not large enough to cover the screen in one dimension. + // Call updateSurfaceSize -- it will only actually do the update if the dimensions + // should change + if (newRotation != mLastRotation) { + // Update surface size (if necessary) + updateSurfaceSize(getSurfaceHolder()); + } SurfaceHolder sh = getSurfaceHolder(); final Rect frame = sh.getSurfaceFrame(); final int dw = frame.width(); final int dh = frame.height(); - int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)). - getDefaultDisplay().getRotation(); boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight; boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation; @@ -343,10 +388,21 @@ public class ImageWallpaper extends WallpaperService { } } - final int availw = dw - mBackground.getWidth(); - final int availh = dh - mBackground.getHeight(); - int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2); - int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2); + // Center the scaled image + mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(), + dh / (float) mBackground.getHeight())); + final int availw = dw - (int) (mBackground.getWidth() * mScale); + final int availh = dh - (int) (mBackground.getHeight() * mScale); + int xPixels = availw / 2; + int yPixels = availh / 2; + + // Adjust the image for xOffset/yOffset values. If window manager is handling offsets, + // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels + // will remain unchanged + final int availwUnscaled = dw - mBackground.getWidth(); + final int availhUnscaled = dh - mBackground.getHeight(); + if (availwUnscaled < 0) xPixels += (int)(availwUnscaled * (mXOffset - .5f) + .5f); + if (availhUnscaled < 0) yPixels += (int)(availhUnscaled * (mYOffset - .5f) + .5f); mOffsetsChanged = false; mRedrawNeeded = false; @@ -354,8 +410,6 @@ public class ImageWallpaper extends WallpaperService { mLastSurfaceWidth = dw; mLastSurfaceHeight = dh; } - mLastXTranslation = xPixels; - mLastYTranslation = yPixels; if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) { if (DEBUG) { Log.d(TAG, "Suppressed drawFrame since the image has not " @@ -363,6 +417,8 @@ public class ImageWallpaper extends WallpaperService { } return; } + mLastXTranslation = xPixels; + mLastYTranslation = yPixels; if (DEBUG) { Log.d(TAG, "Redrawing wallpaper"); @@ -391,7 +447,11 @@ public class ImageWallpaper extends WallpaperService { Throwable exception = null; try { mBackground = null; + mBackgroundWidth = -1; + mBackgroundHeight = -1; mBackground = mWallpaperManager.getBitmap(); + mBackgroundWidth = mBackground.getWidth(); + mBackgroundHeight = mBackground.getHeight(); } catch (RuntimeException e) { exception = e; } catch (OutOfMemoryError e) { @@ -400,6 +460,8 @@ public class ImageWallpaper extends WallpaperService { if (exception != null) { mBackground = null; + mBackgroundWidth = -1; + mBackgroundHeight = -1; // Note that if we do fail at this, and the default wallpaper can't // be loaded, we will go into a cycle. Don't do a build where the // default wallpaper can't be loaded. @@ -413,24 +475,27 @@ public class ImageWallpaper extends WallpaperService { } } - private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) { + private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int left, int top) { Canvas c = sh.lockCanvas(); if (c != null) { try { if (DEBUG) { - Log.d(TAG, "Redrawing: x=" + x + ", y=" + y); + Log.d(TAG, "Redrawing: left=" + left + ", top=" + top); } - c.translate(x, y); + final float right = left + mBackground.getWidth() * mScale; + final float bottom = top + mBackground.getHeight() * mScale; if (w < 0 || h < 0) { c.save(Canvas.CLIP_SAVE_FLAG); - c.clipRect(0, 0, mBackground.getWidth(), mBackground.getHeight(), + c.clipRect(left, top, right, bottom, Op.DIFFERENCE); c.drawColor(0xff000000); c.restore(); } if (mBackground != null) { - c.drawBitmap(mBackground, 0, 0, null); + RectF dest = new RectF(left, top, right, bottom); + // add a filter bitmap? + c.drawBitmap(mBackground, null, dest, null); } } finally { sh.unlockCanvasAndPost(c); @@ -441,8 +506,8 @@ public class ImageWallpaper extends WallpaperService { private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) { if (!initGL(sh)) return false; - final float right = left + mBackground.getWidth(); - final float bottom = top + mBackground.getHeight(); + final float right = left + mBackground.getWidth() * mScale; + final float bottom = top + mBackground.getHeight() * mScale; final Rect frame = sh.getSurfaceFrame(); final Matrix4f ortho = new Matrix4f(); |