Merge "Remove Bluetooth autoconnect on dock"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 253021a..7e4267b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2044,18 +2044,6 @@
</intent-filter>
</activity>
- <receiver
- android:name=".bluetooth.DockEventReceiver">
- <intent-filter>
- <action android:name="android.intent.action.DOCK_EVENT" />
- <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
- <action android:name="android.bluetooth.headset.action.STATE_CHANGED" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
-
- <service android:name=".bluetooth.DockService" />
-
<activity android:name=".bluetooth.RequestPermissionActivity"
android:label="@string/bluetooth_permission_request"
android:excludeFromRecents="true"
diff --git a/src/com/android/settings/bluetooth/DockEventReceiver.java b/src/com/android/settings/bluetooth/DockEventReceiver.java
deleted file mode 100644
index 048b098..0000000
--- a/src/com/android/settings/bluetooth/DockEventReceiver.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2009 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 com.android.settings.bluetooth;
-
-import android.app.Service;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.PowerManager;
-import android.util.Log;
-
-public final class DockEventReceiver extends BroadcastReceiver {
-
- private static final boolean DEBUG = DockService.DEBUG;
-
- private static final String TAG = "DockEventReceiver";
-
- public static final String ACTION_DOCK_SHOW_UI =
- "com.android.settings.bluetooth.action.DOCK_SHOW_UI";
-
- private static final int EXTRA_INVALID = -1234;
-
- private static final Object sStartingServiceSync = new Object();
-
- private static PowerManager.WakeLock sStartingService;
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent == null)
- return;
-
- int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, intent.getIntExtra(
- BluetoothAdapter.EXTRA_STATE, EXTRA_INVALID));
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- if (DEBUG) {
- Log.d(TAG, "Action: " + intent.getAction() + " State:" + state + " Device: "
- + (device == null ? "null" : device.getAliasName()));
- }
-
- if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())
- || ACTION_DOCK_SHOW_UI.endsWith(intent.getAction())) {
- if ((device == null) && (ACTION_DOCK_SHOW_UI.endsWith(intent.getAction()) ||
- ((state != Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
- (state != Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
- if (DEBUG) Log.d(TAG,
- "Wrong state: "+state+" or intent: "+intent.toString()+" with null device");
- return;
- }
-
- switch (state) {
- case Intent.EXTRA_DOCK_STATE_UNDOCKED:
- case Intent.EXTRA_DOCK_STATE_CAR:
- case Intent.EXTRA_DOCK_STATE_DESK:
- case Intent.EXTRA_DOCK_STATE_LE_DESK:
- case Intent.EXTRA_DOCK_STATE_HE_DESK:
- Intent i = new Intent(intent);
- i.setClass(context, DockService.class);
- beginStartingService(context, i);
- break;
- default:
- Log.e(TAG, "Unknown state: " + state);
- break;
- }
- } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction()) ||
- BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
- int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
- BluetoothProfile.STATE_CONNECTED);
- int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-
- /*
- * Reconnect to the dock if:
- * 1) it is a dock
- * 2) it is disconnected
- * 3) the disconnect is initiated remotely
- * 4) the dock is still docked (check can only be done in the Service)
- */
- if (device == null) {
- if (DEBUG) Log.d(TAG, "Device is missing");
- return;
- }
-
- if (newState == BluetoothProfile.STATE_DISCONNECTED &&
- oldState != BluetoothProfile.STATE_DISCONNECTING) {
- // Too bad, the dock state can't be checked from a BroadcastReceiver.
- Intent i = new Intent(intent);
- i.setClass(context, DockService.class);
- beginStartingService(context, i);
- }
-
- } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
- int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
- if (btState != BluetoothAdapter.STATE_TURNING_ON) {
- Intent i = new Intent(intent);
- i.setClass(context, DockService.class);
- beginStartingService(context, i);
- }
- }
- }
-
- /**
- * Start the service to process the current event notifications, acquiring
- * the wake lock before returning to ensure that the service will run.
- */
- private static void beginStartingService(Context context, Intent intent) {
- synchronized (sStartingServiceSync) {
- if (sStartingService == null) {
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- sStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- "StartingDockService");
- }
-
- sStartingService.acquire();
-
- if (context.startService(intent) == null) {
- Log.e(TAG, "Can't start DockService");
- }
- }
- }
-
- /**
- * Called back by the service when it has finished processing notifications,
- * releasing the wake lock if the service is now stopping.
- */
- public static void finishStartingService(Service service, int startId) {
- synchronized (sStartingServiceSync) {
- if (sStartingService != null) {
- if (DEBUG) Log.d(TAG, "stopSelf id = " + startId);
- if (service.stopSelfResult(startId)) {
- Log.d(TAG, "finishStartingService: stopping service");
- sStartingService.release();
- }
- }
- }
- }
-}
diff --git a/src/com/android/settings/bluetooth/DockService.java b/src/com/android/settings/bluetooth/DockService.java
deleted file mode 100644
index 52a015e..0000000
--- a/src/com/android/settings/bluetooth/DockService.java
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- * Copyright (C) 2009 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 com.android.settings.bluetooth;
-
-import android.app.AlertDialog;
-import android.app.Notification;
-import android.app.Service;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-
-import com.android.settings.R;
-import com.android.settingslib.bluetooth.BluetoothCallback;
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
-import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.bluetooth.LocalBluetoothProfile;
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager.ServiceListener;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-public final class DockService extends Service implements ServiceListener {
-
- private static final String TAG = "DockService";
-
- static final boolean DEBUG = false;
-
- // Time allowed for the device to be undocked and redocked without severing
- // the bluetooth connection
- private static final long UNDOCKED_GRACE_PERIOD = 1000;
-
- // Time allowed for the device to be undocked and redocked without turning
- // off Bluetooth
- private static final long DISABLE_BT_GRACE_PERIOD = 2000;
-
- // Msg for user wanting the UI to setup the dock
- private static final int MSG_TYPE_SHOW_UI = 111;
-
- // Msg for device docked event
- private static final int MSG_TYPE_DOCKED = 222;
-
- // Msg for device undocked event
- private static final int MSG_TYPE_UNDOCKED_TEMPORARY = 333;
-
- // Msg for undocked command to be process after UNDOCKED_GRACE_PERIOD millis
- // since MSG_TYPE_UNDOCKED_TEMPORARY
- private static final int MSG_TYPE_UNDOCKED_PERMANENT = 444;
-
- // Msg for disabling bt after DISABLE_BT_GRACE_PERIOD millis since
- // MSG_TYPE_UNDOCKED_PERMANENT
- private static final int MSG_TYPE_DISABLE_BT = 555;
-
- private static final String SHARED_PREFERENCES_NAME = "dock_settings";
-
- private static final String KEY_DISABLE_BT_WHEN_UNDOCKED = "disable_bt_when_undock";
-
- private static final String KEY_DISABLE_BT = "disable_bt";
-
- private static final String KEY_CONNECT_RETRY_COUNT = "connect_retry_count";
-
- /*
- * If disconnected unexpectedly, reconnect up to 6 times. Each profile counts
- * as one time so it's only 3 times for both profiles on the car dock.
- */
- private static final int MAX_CONNECT_RETRY = 6;
-
- private static final int INVALID_STARTID = -100;
-
- // Created in OnCreate()
- private volatile Looper mServiceLooper;
- private volatile ServiceHandler mServiceHandler;
- private Runnable mRunnable;
- private LocalBluetoothAdapter mLocalAdapter;
- private CachedBluetoothDeviceManager mDeviceManager;
- private LocalBluetoothProfileManager mProfileManager;
-
- // Normally set after getting a docked event and unset when the connection
- // is severed. One exception is that mDevice could be null if the service
- // was started after the docked event.
- private BluetoothDevice mDevice;
-
- // Created and used for the duration of the dialog
- private AlertDialog mDialog;
- private LocalBluetoothProfile[] mProfiles;
- private boolean[] mCheckedItems;
- private int mStartIdAssociatedWithDialog;
-
- // Set while BT is being enabled.
- private BluetoothDevice mPendingDevice;
- private int mPendingStartId;
- private int mPendingTurnOnStartId = INVALID_STARTID;
- private int mPendingTurnOffStartId = INVALID_STARTID;
-
- private CheckBox mAudioMediaCheckbox;
-
- @Override
- public void onCreate() {
- if (DEBUG) Log.d(TAG, "onCreate");
-
- LocalBluetoothManager manager = Utils.getLocalBtManager(this);
- if (manager == null) {
- Log.e(TAG, "Can't get LocalBluetoothManager: exiting");
- return;
- }
-
- mLocalAdapter = manager.getBluetoothAdapter();
- mDeviceManager = manager.getCachedDeviceManager();
- mProfileManager = manager.getProfileManager();
- if (mProfileManager == null) {
- Log.e(TAG, "Can't get LocalBluetoothProfileManager: exiting");
- return;
- }
-
- HandlerThread thread = new HandlerThread("DockService");
- thread.start();
-
- mServiceLooper = thread.getLooper();
- mServiceHandler = new ServiceHandler(mServiceLooper);
- }
-
- @Override
- public void onDestroy() {
- if (DEBUG) Log.d(TAG, "onDestroy");
- mRunnable = null;
- if (mDialog != null) {
- mDialog.dismiss();
- mDialog = null;
- }
- if (mProfileManager != null) {
- mProfileManager.removeServiceListener(this);
- }
- if (mServiceLooper != null) {
- mServiceLooper.quit();
- }
-
- mLocalAdapter = null;
- mDeviceManager = null;
- mProfileManager = null;
- mServiceLooper = null;
- mServiceHandler = null;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- // not supported
- return null;
- }
-
- private SharedPreferences getPrefs() {
- return getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE);
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (DEBUG) Log.d(TAG, "onStartCommand startId: " + startId + " flags: " + flags);
-
- if (intent == null) {
- // Nothing to process, stop.
- if (DEBUG) Log.d(TAG, "START_NOT_STICKY - intent is null.");
-
- // NOTE: We MUST not call stopSelf() directly, since we need to
- // make sure the wake lock acquired by the Receiver is released.
- DockEventReceiver.finishStartingService(this, startId);
- return START_NOT_STICKY;
- }
-
- if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
- handleBtStateChange(intent, startId);
- return START_NOT_STICKY;
- }
-
- /*
- * This assumes that the intent sender has checked that this is a dock
- * and that the intent is for a disconnect
- */
- final SharedPreferences prefs = getPrefs();
- if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
- BluetoothDevice disconnectedDevice = intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- int retryCount = prefs.getInt(KEY_CONNECT_RETRY_COUNT, 0);
- if (retryCount < MAX_CONNECT_RETRY) {
- prefs.edit().putInt(KEY_CONNECT_RETRY_COUNT, retryCount + 1).apply();
- handleUnexpectedDisconnect(disconnectedDevice, mProfileManager.getHeadsetProfile(), startId);
- }
- return START_NOT_STICKY;
- } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
- BluetoothDevice disconnectedDevice = intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- int retryCount = prefs.getInt(KEY_CONNECT_RETRY_COUNT, 0);
- if (retryCount < MAX_CONNECT_RETRY) {
- prefs.edit().putInt(KEY_CONNECT_RETRY_COUNT, retryCount + 1).apply();
- handleUnexpectedDisconnect(disconnectedDevice, mProfileManager.getA2dpProfile(), startId);
- }
- return START_NOT_STICKY;
- }
-
- Message msg = parseIntent(intent);
- if (msg == null) {
- // Bad intent
- if (DEBUG) Log.d(TAG, "START_NOT_STICKY - Bad intent.");
- DockEventReceiver.finishStartingService(this, startId);
- return START_NOT_STICKY;
- }
-
- if (msg.what == MSG_TYPE_DOCKED) {
- prefs.edit().remove(KEY_CONNECT_RETRY_COUNT).apply();
- }
-
- msg.arg2 = startId;
- processMessage(msg);
-
- return START_NOT_STICKY;
- }
-
- private final class ServiceHandler extends Handler {
- private ServiceHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- processMessage(msg);
- }
- }
-
- // This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper
- private synchronized void processMessage(Message msg) {
- int msgType = msg.what;
- final int state = msg.arg1;
- final int startId = msg.arg2;
- BluetoothDevice device = null;
- if (msg.obj != null) {
- device = (BluetoothDevice) msg.obj;
- }
-
- if(DEBUG) Log.d(TAG, "processMessage: " + msgType + " state: " + state + " device = "
- + (device == null ? "null" : device.toString()));
-
- boolean deferFinishCall = false;
-
- switch (msgType) {
- case MSG_TYPE_SHOW_UI:
- if (device != null) {
- createDialog(device, state, startId);
- }
- break;
-
- case MSG_TYPE_DOCKED:
- deferFinishCall = msgTypeDocked(device, state, startId);
- break;
-
- case MSG_TYPE_UNDOCKED_PERMANENT:
- deferFinishCall = msgTypeUndockedPermanent(device, startId);
- break;
-
- case MSG_TYPE_UNDOCKED_TEMPORARY:
- msgTypeUndockedTemporary(device, state, startId);
- break;
-
- case MSG_TYPE_DISABLE_BT:
- deferFinishCall = msgTypeDisableBluetooth(startId);
- break;
- }
-
- if (mDialog == null && mPendingDevice == null && msgType != MSG_TYPE_UNDOCKED_TEMPORARY
- && !deferFinishCall) {
- // NOTE: We MUST not call stopSelf() directly, since we need to
- // make sure the wake lock acquired by the Receiver is released.
- DockEventReceiver.finishStartingService(this, startId);
- }
- }
-
- private boolean msgTypeDisableBluetooth(int startId) {
- if (DEBUG) {
- Log.d(TAG, "BT DISABLE");
- }
- final SharedPreferences prefs = getPrefs();
- if (mLocalAdapter.disable()) {
- prefs.edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply();
- return false;
- } else {
- // disable() returned an error. Persist a flag to disable BT later
- prefs.edit().putBoolean(KEY_DISABLE_BT, true).apply();
- mPendingTurnOffStartId = startId;
- if(DEBUG) {
- Log.d(TAG, "disable failed. try again later " + startId);
- }
- return true;
- }
- }
-
- private void msgTypeUndockedTemporary(BluetoothDevice device, int state,
- int startId) {
- // Undocked event received. Queue a delayed msg to sever connection
- Message newMsg = mServiceHandler.obtainMessage(MSG_TYPE_UNDOCKED_PERMANENT, state,
- startId, device);
- mServiceHandler.sendMessageDelayed(newMsg, UNDOCKED_GRACE_PERIOD);
- }
-
- private boolean msgTypeUndockedPermanent(BluetoothDevice device, int startId) {
- // Grace period passed. Disconnect.
- handleUndocked(device);
- if (device != null) {
- final SharedPreferences prefs = getPrefs();
-
- if (DEBUG) {
- Log.d(TAG, "DISABLE_BT_WHEN_UNDOCKED = "
- + prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false));
- }
-
- if (prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false)) {
- if (hasOtherConnectedDevices(device)) {
- // Don't disable BT if something is connected
- prefs.edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply();
- } else {
- // BT was disabled when we first docked
- if (DEBUG) {
- Log.d(TAG, "QUEUED BT DISABLE");
- }
- // Queue a delayed msg to disable BT
- Message newMsg = mServiceHandler.obtainMessage(
- MSG_TYPE_DISABLE_BT, 0, startId, null);
- mServiceHandler.sendMessageDelayed(newMsg,
- DISABLE_BT_GRACE_PERIOD);
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean msgTypeDocked(BluetoothDevice device, final int state,
- final int startId) {
- if (DEBUG) {
- // TODO figure out why hasMsg always returns false if device
- // is supplied
- Log.d(TAG, "1 Has undock perm msg = "
- + mServiceHandler.hasMessages(MSG_TYPE_UNDOCKED_PERMANENT, mDevice));
- Log.d(TAG, "2 Has undock perm msg = "
- + mServiceHandler.hasMessages(MSG_TYPE_UNDOCKED_PERMANENT, device));
- }
-
- mServiceHandler.removeMessages(MSG_TYPE_UNDOCKED_PERMANENT);
- mServiceHandler.removeMessages(MSG_TYPE_DISABLE_BT);
- getPrefs().edit().remove(KEY_DISABLE_BT).apply();
-
- if (device != null) {
- if (!device.equals(mDevice)) {
- if (mDevice != null) {
- // Not expected. Cleanup/undock existing
- handleUndocked(mDevice);
- }
-
- mDevice = device;
-
- // Register first in case LocalBluetoothProfileManager
- // becomes ready after isManagerReady is called and it
- // would be too late to register a service listener.
- mProfileManager.addServiceListener(this);
- if (mProfileManager.isManagerReady()) {
- handleDocked(device, state, startId);
- // Not needed after all
- mProfileManager.removeServiceListener(this);
- } else {
- final BluetoothDevice d = device;
- mRunnable = new Runnable() {
- public void run() {
- handleDocked(d, state, startId); // FIXME: WTF runnable here?
- }
- };
- return true;
- }
- }
- } else {
- // display dialog to enable dock for media audio only in the case of low end docks and
- // if not already selected by user
- int dockAudioMediaEnabled = Settings.Global.getInt(getContentResolver(),
- Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, -1);
- if (dockAudioMediaEnabled == -1 &&
- state == Intent.EXTRA_DOCK_STATE_LE_DESK) {
- handleDocked(null, state, startId);
- return true;
- }
- }
- return false;
- }
-
- synchronized boolean hasOtherConnectedDevices(BluetoothDevice dock) {
- Collection<CachedBluetoothDevice> cachedDevices = mDeviceManager.getCachedDevicesCopy();
- Set<BluetoothDevice> btDevices = mLocalAdapter.getBondedDevices();
- if (btDevices == null || cachedDevices == null || btDevices.isEmpty()) {
- return false;
- }
- if(DEBUG) {
- Log.d(TAG, "btDevices = " + btDevices.size());
- Log.d(TAG, "cachedDeviceUIs = " + cachedDevices.size());
- }
-
- for (CachedBluetoothDevice deviceUI : cachedDevices) {
- BluetoothDevice btDevice = deviceUI.getDevice();
- if (!btDevice.equals(dock) && btDevices.contains(btDevice) && deviceUI
- .isConnected()) {
- if(DEBUG) Log.d(TAG, "connected deviceUI = " + deviceUI.getName());
- return true;
- }
- }
- return false;
- }
-
- private Message parseIntent(Intent intent) {
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, -1234);
-
- if (DEBUG) {
- Log.d(TAG, "Action: " + intent.getAction() + " State:" + state
- + " Device: " + (device == null ? "null" : device.getAliasName()));
- }
-
- int msgType;
- switch (state) {
- case Intent.EXTRA_DOCK_STATE_UNDOCKED:
- msgType = MSG_TYPE_UNDOCKED_TEMPORARY;
- break;
- case Intent.EXTRA_DOCK_STATE_DESK:
- case Intent.EXTRA_DOCK_STATE_HE_DESK:
- case Intent.EXTRA_DOCK_STATE_CAR:
- if (device == null) {
- Log.w(TAG, "device is null");
- return null;
- }
- /// Fall Through ///
- case Intent.EXTRA_DOCK_STATE_LE_DESK:
- if (DockEventReceiver.ACTION_DOCK_SHOW_UI.equals(intent.getAction())) {
- if (device == null) {
- Log.w(TAG, "device is null");
- return null;
- }
- msgType = MSG_TYPE_SHOW_UI;
- } else {
- msgType = MSG_TYPE_DOCKED;
- }
- break;
- default:
- return null;
- }
-
- return mServiceHandler.obtainMessage(msgType, state, 0, device);
- }
-
- private void createDialog(BluetoothDevice device,
- int state, int startId) {
- if (mDialog != null) {
- // Shouldn't normally happen
- mDialog.dismiss();
- mDialog = null;
- }
- mDevice = device;
- switch (state) {
- case Intent.EXTRA_DOCK_STATE_CAR:
- case Intent.EXTRA_DOCK_STATE_DESK:
- case Intent.EXTRA_DOCK_STATE_LE_DESK:
- case Intent.EXTRA_DOCK_STATE_HE_DESK:
- break;
- default:
- return;
- }
-
- startForeground(0, new Notification());
-
- final AlertDialog.Builder ab = new AlertDialog.Builder(this);
- View view;
- LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
-
- mAudioMediaCheckbox = null;
-
- if (device != null) {
- // Device in a new dock.
- boolean firstTime =
- !LocalBluetoothPreferences.hasDockAutoConnectSetting(this, device.getAddress());
-
- CharSequence[] items = initBtSettings(device, state, firstTime);
-
- ab.setTitle(getString(R.string.bluetooth_dock_settings_title));
-
- // Profiles
- ab.setMultiChoiceItems(items, mCheckedItems, mMultiClickListener);
-
- // Remember this settings
- view = inflater.inflate(R.layout.remember_dock_setting, null);
- CheckBox rememberCheckbox = (CheckBox) view.findViewById(R.id.remember);
-
- // check "Remember setting" by default if no value was saved
- boolean checked = firstTime ||
- LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress());
- rememberCheckbox.setChecked(checked);
- rememberCheckbox.setOnCheckedChangeListener(mCheckedChangeListener);
- if (DEBUG) {
- Log.d(TAG, "Auto connect = "
- + LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress()));
- }
- } else {
- ab.setTitle(getString(R.string.bluetooth_dock_settings_title));
-
- view = inflater.inflate(R.layout.dock_audio_media_enable_dialog, null);
- mAudioMediaCheckbox =
- (CheckBox) view.findViewById(R.id.dock_audio_media_enable_cb);
-
- boolean checked = Settings.Global.getInt(getContentResolver(),
- Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
-
- mAudioMediaCheckbox.setChecked(checked);
- mAudioMediaCheckbox.setOnCheckedChangeListener(mCheckedChangeListener);
- }
-
- float pixelScaleFactor = getResources().getDisplayMetrics().density;
- int viewSpacingLeft = (int) (14 * pixelScaleFactor);
- int viewSpacingRight = (int) (14 * pixelScaleFactor);
- ab.setView(view, viewSpacingLeft, 0 /* top */, viewSpacingRight, 0 /* bottom */);
-
- // Ok Button
- ab.setPositiveButton(getString(android.R.string.ok), mClickListener);
-
- mStartIdAssociatedWithDialog = startId;
- mDialog = ab.create();
- mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- mDialog.setOnDismissListener(mDismissListener);
- mDialog.show();
- }
-
- // Called when the individual bt profiles are clicked.
- private final DialogInterface.OnMultiChoiceClickListener mMultiClickListener =
- new DialogInterface.OnMultiChoiceClickListener() {
- public void onClick(DialogInterface dialog, int which, boolean isChecked) {
- if (DEBUG) {
- Log.d(TAG, "Item " + which + " changed to " + isChecked);
- }
- mCheckedItems[which] = isChecked;
- }
- };
-
-
- // Called when the "Remember" Checkbox is clicked
- private final CompoundButton.OnCheckedChangeListener mCheckedChangeListener =
- new CompoundButton.OnCheckedChangeListener() {
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (DEBUG) {
- Log.d(TAG, "onCheckedChanged: Remember Settings = " + isChecked);
- }
- if (mDevice != null) {
- LocalBluetoothPreferences.saveDockAutoConnectSetting(
- DockService.this, mDevice.getAddress(), isChecked);
- } else {
- Settings.Global.putInt(getContentResolver(),
- Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, isChecked ? 1 : 0);
- }
- }
- };
-
-
- // Called when the dialog is dismissed
- private final DialogInterface.OnDismissListener mDismissListener =
- new DialogInterface.OnDismissListener() {
- public void onDismiss(DialogInterface dialog) {
- // NOTE: We MUST not call stopSelf() directly, since we need to
- // make sure the wake lock acquired by the Receiver is released.
- if (mPendingDevice == null) {
- DockEventReceiver.finishStartingService(
- DockService.this, mStartIdAssociatedWithDialog);
- }
- stopForeground(true);
- }
- };
-
- // Called when clicked on the OK button
- private final DialogInterface.OnClickListener mClickListener =
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- if (mDevice != null) {
- if (!LocalBluetoothPreferences
- .hasDockAutoConnectSetting(
- DockService.this,
- mDevice.getAddress())) {
- LocalBluetoothPreferences
- .saveDockAutoConnectSetting(
- DockService.this,
- mDevice.getAddress(), true);
- }
-
- applyBtSettings(mDevice, mStartIdAssociatedWithDialog);
- } else if (mAudioMediaCheckbox != null) {
- Settings.Global.putInt(getContentResolver(),
- Settings.Global.DOCK_AUDIO_MEDIA_ENABLED,
- mAudioMediaCheckbox.isChecked() ? 1 : 0);
- }
- }
- }
- };
-
- private CharSequence[] initBtSettings(BluetoothDevice device,
- int state, boolean firstTime) {
- // TODO Avoid hardcoding dock and profiles. Read from system properties
- int numOfProfiles;
- switch (state) {
- case Intent.EXTRA_DOCK_STATE_DESK:
- case Intent.EXTRA_DOCK_STATE_LE_DESK:
- case Intent.EXTRA_DOCK_STATE_HE_DESK:
- numOfProfiles = 1;
- break;
- case Intent.EXTRA_DOCK_STATE_CAR:
- numOfProfiles = 2;
- break;
- default:
- return null;
- }
-
- mProfiles = new LocalBluetoothProfile[numOfProfiles];
- mCheckedItems = new boolean[numOfProfiles];
- CharSequence[] items = new CharSequence[numOfProfiles];
-
- // FIXME: convert switch to something else
- switch (state) {
- case Intent.EXTRA_DOCK_STATE_CAR:
- items[0] = getString(R.string.bluetooth_dock_settings_headset);
- items[1] = getString(R.string.bluetooth_dock_settings_a2dp);
- mProfiles[0] = mProfileManager.getHeadsetProfile();
- mProfiles[1] = mProfileManager.getA2dpProfile();
- if (firstTime) {
- // Enable by default for car dock
- mCheckedItems[0] = true;
- mCheckedItems[1] = true;
- } else {
- mCheckedItems[0] = mProfiles[0].isPreferred(device);
- mCheckedItems[1] = mProfiles[1].isPreferred(device);
- }
- break;
-
- case Intent.EXTRA_DOCK_STATE_DESK:
- case Intent.EXTRA_DOCK_STATE_LE_DESK:
- case Intent.EXTRA_DOCK_STATE_HE_DESK:
- items[0] = getString(R.string.bluetooth_dock_settings_a2dp);
- mProfiles[0] = mProfileManager.getA2dpProfile();
- if (firstTime) {
- // Disable by default for desk dock
- mCheckedItems[0] = false;
- } else {
- mCheckedItems[0] = mProfiles[0].isPreferred(device);
- }
- break;
- }
- return items;
- }
-
- // TODO: move to background thread to fix strict mode warnings
- private void handleBtStateChange(Intent intent, int startId) {
- int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
- synchronized (this) {
- if(DEBUG) Log.d(TAG, "BtState = " + btState + " mPendingDevice = " + mPendingDevice);
- if (btState == BluetoothAdapter.STATE_ON) {
- handleBluetoothStateOn(startId);
- } else if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
- // Remove the flag to disable BT if someone is turning off bt.
- // The rational is that:
- // a) if BT is off at undock time, no work needs to be done
- // b) if BT is on at undock time, the user wants it on.
- getPrefs().edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply();
- DockEventReceiver.finishStartingService(this, startId);
- } else if (btState == BluetoothAdapter.STATE_OFF) {
- // Bluetooth was turning off as we were trying to turn it on.
- // Let's try again
- if(DEBUG) Log.d(TAG, "Bluetooth = OFF mPendingDevice = " + mPendingDevice);
-
- if (mPendingTurnOffStartId != INVALID_STARTID) {
- DockEventReceiver.finishStartingService(this, mPendingTurnOffStartId);
- getPrefs().edit().remove(KEY_DISABLE_BT).apply();
- mPendingTurnOffStartId = INVALID_STARTID;
- }
-
- if (mPendingDevice != null) {
- mLocalAdapter.enable();
- mPendingTurnOnStartId = startId;
- } else {
- DockEventReceiver.finishStartingService(this, startId);
- }
- }
- }
- }
-
- private void handleBluetoothStateOn(int startId) {
- if (mPendingDevice != null) {
- if (mPendingDevice.equals(mDevice)) {
- if(DEBUG) {
- Log.d(TAG, "applying settings");
- }
- applyBtSettings(mPendingDevice, mPendingStartId);
- } else if(DEBUG) {
- Log.d(TAG, "mPendingDevice (" + mPendingDevice + ") != mDevice ("
- + mDevice + ')');
- }
-
- mPendingDevice = null;
- DockEventReceiver.finishStartingService(this, mPendingStartId);
- } else {
- final SharedPreferences prefs = getPrefs();
- if (DEBUG) {
- Log.d(TAG, "A DISABLE_BT_WHEN_UNDOCKED = "
- + prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false));
- }
- // Reconnect if docked and bluetooth was enabled by user.
- Intent i = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
- if (i != null) {
- int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
- if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- BluetoothDevice device = i
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (device != null) {
- connectIfEnabled(device);
- }
- } else if (prefs.getBoolean(KEY_DISABLE_BT, false)
- && mLocalAdapter.disable()) {
- mPendingTurnOffStartId = startId;
- prefs.edit().remove(KEY_DISABLE_BT).apply();
- return;
- }
- }
- }
-
- if (mPendingTurnOnStartId != INVALID_STARTID) {
- DockEventReceiver.finishStartingService(this, mPendingTurnOnStartId);
- mPendingTurnOnStartId = INVALID_STARTID;
- }
-
- DockEventReceiver.finishStartingService(this, startId);
- }
-
- private synchronized void handleUnexpectedDisconnect(BluetoothDevice disconnectedDevice,
- LocalBluetoothProfile profile, int startId) {
- if (DEBUG) {
- Log.d(TAG, "handling failed connect for " + disconnectedDevice);
- }
-
- // Reconnect if docked.
- if (disconnectedDevice != null) {
- // registerReceiver can't be called from a BroadcastReceiver
- Intent intent = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
- if (intent != null) {
- int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
- if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- BluetoothDevice dockedDevice = intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (dockedDevice != null && dockedDevice.equals(disconnectedDevice)) {
- CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(
- dockedDevice);
- cachedDevice.connectProfile(profile);
- }
- }
- }
- }
-
- DockEventReceiver.finishStartingService(this, startId);
- }
-
- private synchronized void connectIfEnabled(BluetoothDevice device) {
- CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(
- device);
- List<LocalBluetoothProfile> profiles = cachedDevice.getConnectableProfiles();
- for (LocalBluetoothProfile profile : profiles) {
- if (profile.getPreferred(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
- cachedDevice.connect(false);
- return;
- }
- }
- }
-
- private synchronized void applyBtSettings(BluetoothDevice device, int startId) {
- if (device == null || mProfiles == null || mCheckedItems == null
- || mLocalAdapter == null) {
- return;
- }
-
- // Turn on BT if something is enabled
- for (boolean enable : mCheckedItems) {
- if (enable) {
- int btState = mLocalAdapter.getBluetoothState();
- if (DEBUG) {
- Log.d(TAG, "BtState = " + btState);
- }
- // May have race condition as the phone comes in and out and in the dock.
- // Always turn on BT
- mLocalAdapter.enable();
-
- // if adapter was previously OFF, TURNING_OFF, or TURNING_ON
- if (btState != BluetoothAdapter.STATE_ON) {
- if (mPendingDevice != null && mPendingDevice.equals(mDevice)) {
- return;
- }
-
- mPendingDevice = device;
- mPendingStartId = startId;
- if (btState != BluetoothAdapter.STATE_TURNING_ON) {
- getPrefs().edit().putBoolean(
- KEY_DISABLE_BT_WHEN_UNDOCKED, true).apply();
- }
- return;
- }
- }
- }
-
- mPendingDevice = null;
-
- boolean callConnect = false;
- CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(
- device);
- for (int i = 0; i < mProfiles.length; i++) {
- LocalBluetoothProfile profile = mProfiles[i];
- if (DEBUG) Log.d(TAG, profile.toString() + " = " + mCheckedItems[i]);
-
- if (mCheckedItems[i]) {
- // Checked but not connected
- callConnect = true;
- } else if (!mCheckedItems[i]) {
- // Unchecked, may or may not be connected.
- int status = profile.getConnectionStatus(cachedDevice.getDevice());
- if (status == BluetoothProfile.STATE_CONNECTED) {
- if (DEBUG) Log.d(TAG, "applyBtSettings - Disconnecting");
- cachedDevice.disconnect(mProfiles[i]);
- }
- }
- profile.setPreferred(device, mCheckedItems[i]);
- if (DEBUG) {
- if (mCheckedItems[i] != profile.isPreferred(device)) {
- Log.e(TAG, "Can't save preferred value");
- }
- }
- }
-
- if (callConnect) {
- if (DEBUG) Log.d(TAG, "applyBtSettings - Connecting");
- cachedDevice.connect(false);
- }
- }
-
- private synchronized void handleDocked(BluetoothDevice device, int state,
- int startId) {
- if (device != null &&
- LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress())) {
- // Setting == auto connect
- initBtSettings(device, state, false);
- applyBtSettings(mDevice, startId);
- } else {
- createDialog(device, state, startId);
- }
- }
-
- private synchronized void handleUndocked(BluetoothDevice device) {
- mRunnable = null;
- mProfileManager.removeServiceListener(this);
- if (mDialog != null) {
- mDialog.dismiss();
- mDialog = null;
- }
- mDevice = null;
- mPendingDevice = null;
- if (device != null) {
- CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(device);
- cachedDevice.disconnect();
- }
- }
-
- private CachedBluetoothDevice getCachedBluetoothDevice(BluetoothDevice device) {
- CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
- if (cachedDevice == null) {
- cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
- }
- return cachedDevice;
- }
-
- public synchronized void onServiceConnected() {
- if (mRunnable != null) {
- mRunnable.run();
- mRunnable = null;
- mProfileManager.removeServiceListener(this);
- }
- }
-
- public void onServiceDisconnected() {
- // FIXME: shouldn't I do something on service disconnected too?
- }
-
- public static class DockBluetoothCallback implements BluetoothCallback {
- private final Context mContext;
-
- public DockBluetoothCallback(Context context) {
- mContext = context;
- }
-
- public void onBluetoothStateChanged(int bluetoothState) { }
- public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { }
- public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { }
- public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
- public void onScanningStateChanged(boolean started) { }
-
- @Override
- public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
- BluetoothDevice device = cachedDevice.getDevice();
- if (bondState == BluetoothDevice.BOND_NONE) {
- if (device.isBluetoothDock()) {
- // After a dock is unpaired, we will forget the settings
- LocalBluetoothPreferences
- .removeDockAutoConnectSetting(mContext, device.getAddress());
-
- // if the device is undocked, remove it from the list as well
- if (!device.getAddress().equals(getDockedDeviceAddress(mContext))) {
- cachedDevice.setVisible(false);
- }
- }
- }
- }
-
- // This can't be called from a broadcast receiver where the filter is set in the Manifest.
- private static String getDockedDeviceAddress(Context context) {
- // This works only because these broadcast intents are "sticky"
- Intent i = context.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
- if (i != null) {
- int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
- if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (device != null) {
- return device.getAddress();
- }
- }
- }
- return null;
- }
- }
-}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
index 6a0bdcf..19eb200 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
@@ -44,8 +44,6 @@
private static final String KEY_LAST_SELECTED_DEVICE_TIME = "last_selected_device_time";
- private static final String KEY_DOCK_AUTO_CONNECT = "auto_connect_to_dock";
-
private static final String KEY_DISCOVERABLE_END_TIMESTAMP = "discoverable_end_timestamp";
private LocalBluetoothPreferences() {
@@ -147,25 +145,4 @@
editor.putLong(KEY_DISCOVERABLE_END_TIMESTAMP, endTimestamp);
editor.apply();
}
-
- static boolean hasDockAutoConnectSetting(Context context, String addr) {
- return getSharedPreferences(context).contains(KEY_DOCK_AUTO_CONNECT + addr);
- }
-
- static boolean getDockAutoConnectSetting(Context context, String addr) {
- return getSharedPreferences(context).getBoolean(KEY_DOCK_AUTO_CONNECT + addr,
- false);
- }
-
- static void saveDockAutoConnectSetting(Context context, String addr, boolean autoConnect) {
- SharedPreferences.Editor editor = getSharedPreferences(context).edit();
- editor.putBoolean(KEY_DOCK_AUTO_CONNECT + addr, autoConnect);
- editor.apply();
- }
-
- static void removeDockAutoConnectSetting(Context context, String addr) {
- SharedPreferences.Editor editor = getSharedPreferences(context).edit();
- editor.remove(KEY_DOCK_AUTO_CONNECT + addr);
- editor.apply();
- }
}
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
index 2cbe473..b74191e 100755
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -23,7 +23,6 @@
import android.widget.Toast;
import com.android.settings.R;
-import com.android.settings.bluetooth.DockService.DockBluetoothCallback;
import com.android.settings.search.Index;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -84,11 +83,6 @@
// TODO: wire this up to show connection errors...
static void showConnectingError(Context context, String name) {
- // if (!mIsConnectingErrorPossible) {
- // return;
- // }
- // mIsConnectingErrorPossible = false;
-
showError(context, name, R.string.bluetooth_connecting_error_message);
}
@@ -137,8 +131,6 @@
@Override
public void onBluetoothManagerInitialized(Context appContext,
LocalBluetoothManager bluetoothManager) {
- bluetoothManager.getEventManager().registerCallback(
- new DockBluetoothCallback(appContext));
com.android.settingslib.bluetooth.Utils.setErrorListener(mErrorListener);
}
};