diff options
Diffstat (limited to 'src/com/android/settings/bluetooth/LocalBluetoothManager.java')
-rw-r--r-- | src/com/android/settings/bluetooth/LocalBluetoothManager.java | 382 |
1 files changed, 51 insertions, 331 deletions
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java index f3c5e6f30..0c04e2273 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2011 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. @@ -16,376 +16,96 @@ package com.android.settings.bluetooth; -import com.android.settings.R; - -import android.app.Activity; -import android.app.AlertDialog; -import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.content.Context; -import android.content.SharedPreferences; -import android.os.ParcelUuid; -import android.util.Config; import android.util.Log; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; -// TODO: have some notion of shutting down. Maybe a minute after they leave BT settings? /** * LocalBluetoothManager provides a simplified interface on top of a subset of - * the Bluetooth API. + * the Bluetooth API. Note that {@link #getInstance} will return null + * if there is no Bluetooth adapter on this device, and callers must be + * prepared to handle this case. */ -public class LocalBluetoothManager { +public final class LocalBluetoothManager { private static final String TAG = "LocalBluetoothManager"; - static final boolean V = Config.LOGV; - static final boolean D = Config.LOGD; - - private static final String SHARED_PREFERENCES_NAME = "bluetooth_settings"; /** Singleton instance. */ private static LocalBluetoothManager sInstance; - private Context mContext; - /** If a BT-related activity is in the foreground, this will be it. */ - private Activity mForegroundActivity; - private AlertDialog mErrorDialog = null; - - private BluetoothAdapter mAdapter; - - private CachedBluetoothDeviceManager mCachedDeviceManager; - private BluetoothA2dp mBluetoothA2dp; - - private int mState = BluetoothAdapter.ERROR; + private final Context mContext; - private final List<Callback> mCallbacks = new ArrayList<Callback>(); - - private static final int SCAN_EXPIRATION_MS = 5 * 60 * 1000; // 5 mins - - // If a device was picked from the device picker or was in discoverable mode - // in the last 60 seconds, show the pairing dialogs in foreground instead - // of raising notifications - private static final int GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND = 60 * 1000; - - public static final String SHARED_PREFERENCES_KEY_DISCOVERING_TIMESTAMP = - "last_discovering_time"; - - private static final String SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE = - "last_selected_device"; + /** If a BT-related activity is in the foreground, this will be it. */ + private Context mForegroundActivity; - private static final String SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE_TIME = - "last_selected_device_time"; + private final LocalBluetoothAdapter mLocalAdapter; - private static final String SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT = "auto_connect_to_dock"; + private final CachedBluetoothDeviceManager mCachedDeviceManager; - private long mLastScan; + /** The Bluetooth profile manager. */ + private final LocalBluetoothProfileManager mProfileManager; - private LocalBluetoothManager() { } + /** The broadcast receiver event manager. */ + private final BluetoothEventManager mEventManager; - public static LocalBluetoothManager getInstance(Context context) { - synchronized (LocalBluetoothManager.class) { - if (sInstance == null) { - sInstance = new LocalBluetoothManager(); - if (!sInstance.init(context)) { - return null; - } - LocalBluetoothProfileManager.init(sInstance); + public static synchronized LocalBluetoothManager getInstance(Context context) { + if (sInstance == null) { + LocalBluetoothAdapter adapter = LocalBluetoothAdapter.getInstance(); + if (adapter == null) { + return null; } - - return sInstance; - } - } - - private boolean init(Context context) { - // This will be around as long as this process is - mContext = context.getApplicationContext(); - - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - return false; + // This will be around as long as this process is + Context appContext = context.getApplicationContext(); + sInstance = new LocalBluetoothManager(adapter, appContext); } - mCachedDeviceManager = new CachedBluetoothDeviceManager(this); - - new BluetoothEventRedirector(this).registerReceiver(); + return sInstance; + } - mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP); + private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context) { + mContext = context; + mLocalAdapter = adapter; - return true; + mCachedDeviceManager = new CachedBluetoothDeviceManager(); + mEventManager = new BluetoothEventManager(mLocalAdapter, + mCachedDeviceManager); + mProfileManager = new LocalBluetoothProfileManager(context, + mLocalAdapter, mCachedDeviceManager, mEventManager); } - private final BluetoothProfile.ServiceListener mProfileListener = - new BluetoothProfile.ServiceListener() { - public void onServiceConnected(int profile, BluetoothProfile proxy) { - mBluetoothA2dp = (BluetoothA2dp) proxy; - } - public void onServiceDisconnected(int profile) { - mBluetoothA2dp = null; - } - }; - - public BluetoothAdapter getBluetoothAdapter() { - return mAdapter; + public LocalBluetoothAdapter getBluetoothAdapter() { + return mLocalAdapter; } public Context getContext() { return mContext; } - public Activity getForegroundActivity() { - return mForegroundActivity; - } - - public void setForegroundActivity(Activity activity) { - if (mErrorDialog != null) { - mErrorDialog.dismiss(); - mErrorDialog = null; - } - mForegroundActivity = activity; + boolean isForegroundActivity() { + return mForegroundActivity != null; } - public SharedPreferences getSharedPreferences() { - return mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - } - - public CachedBluetoothDeviceManager getCachedDeviceManager() { - return mCachedDeviceManager; - } - - List<Callback> getCallbacks() { - return mCallbacks; - } - - public void registerCallback(Callback callback) { - synchronized (mCallbacks) { - mCallbacks.add(callback); - } - } - - public void unregisterCallback(Callback callback) { - synchronized (mCallbacks) { - mCallbacks.remove(callback); - } - } - - public void startScanning(boolean force) { - if (mAdapter.isDiscovering()) { - /* - * Already discovering, but give the callback that information. - * Note: we only call the callbacks, not the same path as if the - * scanning state had really changed (in that case the device - * manager would clear its list of unpaired scanned devices). - */ - dispatchScanningStateChanged(true); + synchronized void setForegroundActivity(Context context) { + if (context != null) { + Log.d(TAG, "setting foreground activity to non-null context"); + mForegroundActivity = context; + mEventManager.resume(context); } else { - if (!force) { - // Don't scan more than frequently than SCAN_EXPIRATION_MS, - // unless forced - if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) { - return; - } - - // If we are playing music, don't scan unless forced. - if (mBluetoothA2dp != null) { - List<BluetoothDevice> sinks = mBluetoothA2dp.getConnectedDevices(); - if (sinks.size() > 0) { - if (mBluetoothA2dp.isA2dpPlaying(sinks.get(0))) return; - } - } + if (mForegroundActivity != null) { + Log.d(TAG, "setting foreground activity to null"); + mEventManager.pause(mForegroundActivity); + mForegroundActivity = null; } - - if (mAdapter.startDiscovery()) { - mLastScan = System.currentTimeMillis(); - } - } - } - - public void stopScanning() { - if (mAdapter.isDiscovering()) { - mAdapter.cancelDiscovery(); - } - } - - public int getBluetoothState() { - - if (mState == BluetoothAdapter.ERROR) { - syncBluetoothState(); } - - return mState; } - void setBluetoothStateInt(int state) { - mState = state; - - if (state == BluetoothAdapter.STATE_ON) { - ParcelUuid[] uuids = mAdapter.getUuids(); - LocalBluetoothProfileManager.updateLocalProfiles(getInstance(mContext), uuids); - } - - if (state == BluetoothAdapter.STATE_ON || - state == BluetoothAdapter.STATE_OFF) { - mCachedDeviceManager.onBluetoothStateChanged(state == - BluetoothAdapter.STATE_ON); - } - } - - private void syncBluetoothState() { - int bluetoothState; - - if (mAdapter != null) { - bluetoothState = mAdapter.isEnabled() - ? BluetoothAdapter.STATE_ON - : BluetoothAdapter.STATE_OFF; - } else { - bluetoothState = BluetoothAdapter.ERROR; - } - - setBluetoothStateInt(bluetoothState); - } - - public void setBluetoothEnabled(boolean enabled) { - boolean wasSetStateSuccessful = enabled - ? mAdapter.enable() - : mAdapter.disable(); - - if (wasSetStateSuccessful) { - setBluetoothStateInt(enabled - ? BluetoothAdapter.STATE_TURNING_ON - : BluetoothAdapter.STATE_TURNING_OFF); - } else { - if (V) { - Log.v(TAG, - "setBluetoothEnabled call, manager didn't return success for enabled: " - + enabled); - } - - syncBluetoothState(); - } - } - - /** - * @param started True if scanning started, false if scanning finished. - */ - void onScanningStateChanged(boolean started) { - // TODO: have it be a callback (once we switch bluetooth state changed to callback) - mCachedDeviceManager.onScanningStateChanged(started); - dispatchScanningStateChanged(started); - } - - private void dispatchScanningStateChanged(boolean started) { - synchronized (mCallbacks) { - for (Callback callback : mCallbacks) { - callback.onScanningStateChanged(started); - } - } - } - - public void showError(BluetoothDevice device, int messageResId) { - CachedBluetoothDevice cachedDevice = mCachedDeviceManager.findDevice(device); - String name = null; - if (cachedDevice == null) { - if (device != null) name = device.getName(); - - if (name == null) { - name = mContext.getString(R.string.bluetooth_remote_device); - } - } else { - name = cachedDevice.getName(); - } - String message = mContext.getString(messageResId, name); - - if (mForegroundActivity != null) { - // Need an activity context to show a dialog - mErrorDialog = new AlertDialog.Builder(mForegroundActivity) - .setIcon(android.R.drawable.ic_dialog_alert) - .setTitle(R.string.bluetooth_error_title) - .setMessage(message) - .setPositiveButton(android.R.string.ok, null) - .show(); - } else { - // Fallback on a toast - Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); - } - } - - public interface Callback { - void onScanningStateChanged(boolean started); - void onDeviceAdded(CachedBluetoothDevice cachedDevice); - void onDeviceDeleted(CachedBluetoothDevice cachedDevice); - void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState); - } - - public boolean shouldShowDialogInForeground(String deviceAddress) { - // If Bluetooth Settings is visible - if (mForegroundActivity != null) return true; - - long currentTimeMillis = System.currentTimeMillis(); - SharedPreferences sharedPreferences = getSharedPreferences(); - - // If the device was in discoverABLE mode recently - long lastDiscoverableEndTime = sharedPreferences.getLong( - BluetoothDiscoverableEnabler.SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0); - if ((lastDiscoverableEndTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) - > currentTimeMillis) { - return true; - } - - // If the device was discoverING recently - if (mAdapter != null && mAdapter.isDiscovering()) { - return true; - } else if ((sharedPreferences.getLong(SHARED_PREFERENCES_KEY_DISCOVERING_TIMESTAMP, 0) + - GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) > currentTimeMillis) { - return true; - } - - // If the device was picked in the device picker recently - if (deviceAddress != null) { - String lastSelectedDevice = sharedPreferences.getString( - SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE, null); - - if (deviceAddress.equals(lastSelectedDevice)) { - long lastDeviceSelectedTime = sharedPreferences.getLong( - SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE_TIME, 0); - if ((lastDeviceSelectedTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) - > currentTimeMillis) { - return true; - } - } - } - return false; - } - - void persistSelectedDeviceInPicker(String deviceAddress) { - SharedPreferences.Editor editor = getSharedPreferences().edit(); - editor.putString(LocalBluetoothManager.SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE, - deviceAddress); - editor.putLong(LocalBluetoothManager.SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE_TIME, - System.currentTimeMillis()); - editor.apply(); - } - - public boolean hasDockAutoConnectSetting(String addr) { - return getSharedPreferences().contains(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr); - } - - public boolean getDockAutoConnectSetting(String addr) { - return getSharedPreferences().getBoolean(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr, - false); + CachedBluetoothDeviceManager getCachedDeviceManager() { + return mCachedDeviceManager; } - public void saveDockAutoConnectSetting(String addr, boolean autoConnect) { - SharedPreferences.Editor editor = getSharedPreferences().edit(); - editor.putBoolean(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr, autoConnect); - editor.apply(); + BluetoothEventManager getEventManager() { + return mEventManager; } - public void removeDockAutoConnectSetting(String addr) { - SharedPreferences.Editor editor = getSharedPreferences().edit(); - editor.remove(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr); - editor.apply(); + LocalBluetoothProfileManager getProfileManager() { + return mProfileManager; } } |