diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-02 22:54:33 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-02 22:54:33 -0800 |
commit | 3dec7d563a2f3e1eb967ce2054a00b6620e3558c (patch) | |
tree | aa3b0365c47cb3c1607c0dc76c8d32b4046fc287 /core/java/android/server | |
parent | 15ab3eae2ec3d73b3e8aa60b33ae41445bf83f4b (diff) | |
download | frameworks_base-3dec7d563a2f3e1eb967ce2054a00b6620e3558c.zip frameworks_base-3dec7d563a2f3e1eb967ce2054a00b6620e3558c.tar.gz frameworks_base-3dec7d563a2f3e1eb967ce2054a00b6620e3558c.tar.bz2 |
auto import from //depot/cupcake/@137055
Diffstat (limited to 'core/java/android/server')
-rw-r--r-- | core/java/android/server/BluetoothA2dpService.java | 82 | ||||
-rw-r--r-- | core/java/android/server/BluetoothDeviceService.java | 24 | ||||
-rw-r--r-- | core/java/android/server/search/SearchableInfo.java | 18 |
3 files changed, 105 insertions, 19 deletions
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 58f9491..f8bc765 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -15,8 +15,7 @@ */ /** - * TODO: Move this to - * java/services/com/android/server/BluetoothA2dpService.java + * TODO: Move this to services.jar * and make the contructor package private again. * @hide */ @@ -35,15 +34,16 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.media.AudioManager; import android.os.Binder; +import android.os.Handler; +import android.os.Message; import android.provider.Settings; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.List; import java.util.HashMap; -import java.util.Iterator; +import java.util.List; public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private static final String TAG = "BluetoothA2dpService"; @@ -57,6 +57,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private static final String A2DP_SINK_ADDRESS = "a2dp_sink_address"; private static final String BLUETOOTH_ENABLED = "bluetooth_enabled"; + private static final int MESSAGE_CONNECT_TO = 1; + private final Context mContext; private final IntentFilter mIntentFilter; private HashMap<String, SinkState> mAudioDevices; @@ -86,6 +88,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION); mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION); mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION); + mIntentFilter.addAction(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION); mContext.registerReceiver(mReceiver, mIntentFilter); if (device.isEnabled()) { @@ -123,6 +126,37 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF); break; } + } else if (action.equals(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION)) { + if (getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF) { + // This device is a preferred sink. Make an A2DP connection + // after a delay. We delay to avoid connection collisions, + // and to give other profiles such as HFP a chance to + // connect first. + Message msg = Message.obtain(mHandler, MESSAGE_CONNECT_TO, address); + mHandler.sendMessageDelayed(msg, 6000); + } + } + } + }; + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_CONNECT_TO: + String address = (String)msg.obj; + // check device is still preferred, and nothing is currently + // connected + if (getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF && + lookupSinksMatchingStates(new int[] { + BluetoothA2dp.STATE_CONNECTING, + BluetoothA2dp.STATE_CONNECTED, + BluetoothA2dp.STATE_PLAYING, + BluetoothA2dp.STATE_DISCONNECTING}).size() == 0) { + log("Auto-connecting A2DP to sink " + address); + connectSink(address); + } + break; } } }; @@ -142,7 +176,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private synchronized void onBluetoothDisable() { if (mAudioDevices != null) { - for (String path : mAudioDevices.keySet()) { + // copy to allow modification during iteration + String[] paths = new String[mAudioDevices.size()]; + paths = mAudioDevices.keySet().toArray(paths); + for (String path : paths) { switch (mAudioDevices.get(path).state) { case BluetoothA2dp.STATE_CONNECTING: case BluetoothA2dp.STATE_CONNECTED: @@ -234,17 +271,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { public synchronized List<String> listConnectedSinks() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - List<String> connectedSinks = new ArrayList<String>(); - if (mAudioDevices == null) { - return connectedSinks; - } - for (SinkState sink : mAudioDevices.values()) { - if (sink.state == BluetoothA2dp.STATE_CONNECTED || - sink.state == BluetoothA2dp.STATE_PLAYING) { - connectedSinks.add(sink.address); - } - } - return connectedSinks; + return lookupSinksMatchingStates(new int[] {BluetoothA2dp.STATE_CONNECTED, + BluetoothA2dp.STATE_PLAYING}); } public synchronized int getSinkState(String address) { @@ -298,7 +326,11 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { // bluez 3.36 quietly disconnects the previous sink when a new sink // is connected, so we need to mark all previously connected sinks as // disconnected - for (String oldPath : mAudioDevices.keySet()) { + + // copy to allow modification during iteration + String[] paths = new String[mAudioDevices.size()]; + paths = mAudioDevices.keySet().toArray(paths); + for (String oldPath : paths) { if (path.equals(oldPath)) { continue; } @@ -350,6 +382,22 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { return null; } + private synchronized List<String> lookupSinksMatchingStates(int[] states) { + List<String> sinks = new ArrayList<String>(); + if (mAudioDevices == null) { + return sinks; + } + for (SinkState sink : mAudioDevices.values()) { + for (int state : states) { + if (sink.state == state) { + sinks.add(sink.address); + break; + } + } + } + return sinks; + } + private synchronized void updateState(String path, int state) { if (mAudioDevices == null) return; diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index fa53a60..950ff3a 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -141,6 +141,20 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED, BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); } + + // Remove remoteServiceChannelCallbacks + HashMap<String, IBluetoothDeviceCallback> callbacksMap = + mEventLoop.getRemoteServiceChannelCallbacks(); + IBluetoothDeviceCallback callback; + + for (String address : callbacksMap.keySet()) { + callback = callbacksMap.get(address); + try { + callback.onGetRemoteServiceChannelResult(address, BluetoothError.ERROR_DISABLED); + } catch (RemoteException e) {} + callbacksMap.remove(address); + } + // update mode Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION); intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE); @@ -569,10 +583,18 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } address = address.toUpperCase(); + String[] bonding = mBondState.listInState(BluetoothDevice.BOND_BONDING); + if (bonding.length > 0 && !bonding[0].equals(address)) { + log("Ignoring createBond(): another device is bonding"); + // a different device is currently bonding, fail + return false; + } + // Check for bond state only if we are not performing auto // pairing exponential back-off attempts. if (!mBondState.isAutoPairingAttemptsInProgress(address) && - mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) { + mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) { + log("Ignoring createBond(): this device is already bonding or bonded"); return false; } diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index c18675e..0c04839 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -35,6 +35,7 @@ import android.text.InputType; import android.util.AttributeSet; import android.util.Log; import android.util.Xml; +import android.view.inputmethod.EditorInfo; import java.io.IOException; import java.util.ArrayList; @@ -77,6 +78,7 @@ public final class SearchableInfo implements Parcelable { private int mIconId = 0; private int mSearchButtonText = 0; private int mSearchInputType = 0; + private int mSearchImeOptions = 0; private String mSuggestAuthority = null; private String mSuggestPath = null; private String mSuggestSelection = null; @@ -429,8 +431,9 @@ public final class SearchableInfo implements Parcelable { com.android.internal.R.styleable.Searchable_searchButtonText, 0); mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType, InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_FLAG_SEARCH | InputType.TYPE_TEXT_VARIATION_NORMAL); + mSearchImeOptions = a.getInt(com.android.internal.R.styleable.Searchable_imeOptions, + EditorInfo.IME_ACTION_SEARCH); setSearchModeFlags(); if (DBG_INHIBIT_SUGGESTIONS == 0) { @@ -743,6 +746,17 @@ public final class SearchableInfo implements Parcelable { } /** + * Return the input method options specified in the searchable attributes. + * This will default to EditorInfo.ACTION_SEARCH if not specified (which is + * appropriate for a search box). + * + * @return the input type + */ + public int getImeOptions() { + return mSearchImeOptions; + } + + /** * Return the list of searchable activities, for use in the drop-down. */ public static ArrayList<SearchableInfo> getSearchablesList() { @@ -782,6 +796,7 @@ public final class SearchableInfo implements Parcelable { mIconId = in.readInt(); mSearchButtonText = in.readInt(); mSearchInputType = in.readInt(); + mSearchImeOptions = in.readInt(); setSearchModeFlags(); mSuggestAuthority = in.readString(); @@ -818,6 +833,7 @@ public final class SearchableInfo implements Parcelable { dest.writeInt(mIconId); dest.writeInt(mSearchButtonText); dest.writeInt(mSearchInputType); + dest.writeInt(mSearchImeOptions); dest.writeString(mSuggestAuthority); dest.writeString(mSuggestPath); |