summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/bluetooth
diff options
context:
space:
mode:
authorMichael Chan <mchan@android.com>2009-12-07 20:50:54 -0800
committerAndroid Git Automerger <android-git-automerger@android.com>2009-12-07 20:50:54 -0800
commit4e1e2d2bf674e5edf5a09e6788690851ae9a53f3 (patch)
treef9518d40da8ebd6da6f25de644cca6125f30f327 /src/com/android/settings/bluetooth
parentb659c9e4102304b9c41558a2b8eaccc03c96a9e2 (diff)
parent0c75b2d2dc35b88d5cb9db96afc72ed074ca5350 (diff)
downloadpackages_apps_settings-4e1e2d2bf674e5edf5a09e6788690851ae9a53f3.zip
packages_apps_settings-4e1e2d2bf674e5edf5a09e6788690851ae9a53f3.tar.gz
packages_apps_settings-4e1e2d2bf674e5edf5a09e6788690851ae9a53f3.tar.bz2
am 0c75b2d2: Merge change I80790bdb into eclair
Merge commit '0c75b2d2dc35b88d5cb9db96afc72ed074ca5350' into eclair-plus-aosp * commit '0c75b2d2dc35b88d5cb9db96afc72ed074ca5350': b/2296110 Dialog for setting up dock audio.
Diffstat (limited to 'src/com/android/settings/bluetooth')
-rw-r--r--src/com/android/settings/bluetooth/CachedBluetoothDevice.java64
-rw-r--r--src/com/android/settings/bluetooth/DockAudioStateChangeReceiver.java76
-rw-r--r--src/com/android/settings/bluetooth/DockEventReceiver.java112
-rw-r--r--src/com/android/settings/bluetooth/DockService.java495
-rw-r--r--src/com/android/settings/bluetooth/DockSettingsActivity.java312
5 files changed, 640 insertions, 419 deletions
diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
index f749cf7..c3b97f6 100644
--- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
@@ -227,44 +227,46 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
public void onProfileStateChanged(Profile profile, int newProfileState) {
- if (D) {
- Log.d(TAG, "onProfileStateChanged:" + workQueue.toString());
- }
-
- int newState = LocalBluetoothProfileManager.getProfileManager(mLocalManager,
- profile).convertState(newProfileState);
-
- if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED) {
- if (!mProfiles.contains(profile)) {
- mProfiles.add(profile);
+ synchronized (workQueue) {
+ if (D) {
+ Log.d(TAG, "onProfileStateChanged:" + workQueue.toString());
}
- }
- /* Ignore the transient states e.g. connecting, disconnecting */
- if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED ||
- newState == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) {
- BluetoothJob job = workQueue.peek();
- if (job == null) {
- return;
- } else if (!job.cachedDevice.mDevice.equals(mDevice)) {
- // This can happen in 2 cases: 1) BT device initiated pairing and
- // 2) disconnects of one headset that's triggered by connects of
- // another.
- if (D) {
- Log.d(TAG, "mDevice:" + mDevice + " != head:" + job.toString());
+ int newState = LocalBluetoothProfileManager.getProfileManager(mLocalManager,
+ profile).convertState(newProfileState);
+
+ if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED) {
+ if (!mProfiles.contains(profile)) {
+ mProfiles.add(profile);
}
+ }
- // Check to see if we need to remove the stale items from the queue
- if (!pruneQueue(null)) {
- // nothing in the queue was modify. Just ignore the notification and return.
+ /* Ignore the transient states e.g. connecting, disconnecting */
+ if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED ||
+ newState == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) {
+ BluetoothJob job = workQueue.peek();
+ if (job == null) {
return;
+ } else if (!job.cachedDevice.mDevice.equals(mDevice)) {
+ // This can happen in 2 cases: 1) BT device initiated pairing and
+ // 2) disconnects of one headset that's triggered by connects of
+ // another.
+ if (D) {
+ Log.d(TAG, "mDevice:" + mDevice + " != head:" + job.toString());
+ }
+
+ // Check to see if we need to remove the stale items from the queue
+ if (!pruneQueue(null)) {
+ // nothing in the queue was modify. Just ignore the notification and return.
+ return;
+ }
+ } else {
+ // Remove the first item and process the next one
+ workQueue.poll();
}
- } else {
- // Remove the first item and process the next one
- workQueue.poll();
- }
- processCommands();
+ processCommands();
+ }
}
}
diff --git a/src/com/android/settings/bluetooth/DockAudioStateChangeReceiver.java b/src/com/android/settings/bluetooth/DockAudioStateChangeReceiver.java
deleted file mode 100644
index d320742..0000000
--- a/src/com/android/settings/bluetooth/DockAudioStateChangeReceiver.java
+++ /dev/null
@@ -1,76 +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.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-public class DockAudioStateChangeReceiver extends BroadcastReceiver {
-
- private static final boolean DBG = true;
- private static final String TAG = "DockAudioStateChangeReceiver";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent == null)
- return;
-
- if (DBG) {
- Log.e(TAG, "Action:" + intent.getAction()
- + " State:" + intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED));
- }
-
- if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (device == null) {
- if (DBG) Log.e(TAG, "Device is missing");
- return;
- }
-
- LocalBluetoothManager localManager = LocalBluetoothManager.getInstance(context);
-
- int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
-
- switch (state) {
- case Intent.EXTRA_DOCK_STATE_UNDOCKED:
- DockSettingsActivity.handleUndocked(context, localManager, device);
- break;
- case Intent.EXTRA_DOCK_STATE_CAR:
- case Intent.EXTRA_DOCK_STATE_DESK:
- if (DockSettingsActivity.getAutoConnectSetting(localManager)) {
- // Auto connect
- DockSettingsActivity.handleDocked(context, localManager, device, state);
- } else {
- // Don't auto connect. Show dialog.
- Intent i = new Intent(intent);
- i.setClass(context, DockSettingsActivity.class);
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(i);
- }
- break;
- default:
- Log.e(TAG, "Unknown state");
- break;
- }
- }
- }
-}
diff --git a/src/com/android/settings/bluetooth/DockEventReceiver.java b/src/com/android/settings/bluetooth/DockEventReceiver.java
new file mode 100644
index 0000000..a2678b9
--- /dev/null
+++ b/src/com/android/settings/bluetooth/DockEventReceiver.java
@@ -0,0 +1,112 @@
+/*
+ * 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.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.util.Log;
+
+public class DockEventReceiver extends BroadcastReceiver {
+
+ private static final boolean DEBUG = true;
+
+ 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;
+
+ static final Object mStartingServiceSync = new Object();
+
+ static PowerManager.WakeLock mStartingService;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null)
+ return;
+
+ int state = intent.getIntExtra(Intent.EXTRA_DOCK_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.getName()));
+ }
+
+ if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())
+ || ACTION_DOCK_SHOW_UI.endsWith(intent.getAction())) {
+ if (device == null) {
+ if (DEBUG) Log.e(TAG, "Device is missing");
+ return;
+ }
+
+ switch (state) {
+ case Intent.EXTRA_DOCK_STATE_UNDOCKED:
+ case Intent.EXTRA_DOCK_STATE_CAR:
+ case Intent.EXTRA_DOCK_STATE_DESK:
+ Intent i = new Intent(intent);
+ i.setClass(context, DockService.class);
+ beginStartingService(context, i);
+ break;
+ default:
+ if (DEBUG) Log.e(TAG, "Unknown state");
+ break;
+ }
+ }
+ }
+
+ /**
+ * Start the service to process the current event notifications, acquiring
+ * the wake lock before returning to ensure that the service will run.
+ */
+ public static void beginStartingService(Context context, Intent intent) {
+ synchronized (mStartingServiceSync) {
+ if (mStartingService == null) {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "StartingDockService");
+ mStartingService.setReferenceCounted(false);
+ }
+
+ mStartingService.acquire();
+
+ if (context.startService(intent) == null) {
+ Log.e(TAG, "Can't start DockService");
+ mStartingService.release();
+ }
+ }
+ }
+
+ /**
+ * 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 (mStartingServiceSync) {
+ if (mStartingService != null) {
+ if (service.stopSelfResult(startId)) {
+ mStartingService.release();
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/bluetooth/DockService.java b/src/com/android/settings/bluetooth/DockService.java
new file mode 100644
index 0000000..245b10d
--- /dev/null
+++ b/src/com/android/settings/bluetooth/DockService.java
@@ -0,0 +1,495 @@
+/*
+ * 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 com.android.settings.R;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+
+import android.app.AlertDialog;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+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.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+public class DockService extends Service implements AlertDialog.OnMultiChoiceClickListener,
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
+ CompoundButton.OnCheckedChangeListener {
+
+ // TODO check for waitlock leak
+ // TODO check for service shutting down properly
+ // TODO sticky vs non-sticky
+ // TODO clean up static functions
+ // TODO test after wiping data
+
+ private static final String TAG = "DockService";
+
+ // TODO clean up logs. Disable DEBUG flag for this file and receiver's too
+ private static final boolean DEBUG = true;
+
+ private static final String SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK = "auto_connect_to_dock";
+
+ // Time allowed for the device to be undocked and redocked without severing
+ // the bluetooth connection
+ private static final long UNDOCKED_GRACE_PERIOD = 1000;
+
+ // 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;
+
+ // Created in OnCreate()
+ private volatile Looper mServiceLooper;
+ private volatile ServiceHandler mServiceHandler;
+ private DockService mContext;
+ private LocalBluetoothManager mBtManager;
+
+ // 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 Profile[] mProfiles;
+ private boolean[] mCheckedItems;
+ private int mStartIdAssociatedWithDialog;
+
+ @Override
+ public void onCreate() {
+ if (DEBUG) Log.d(TAG, "onCreate");
+
+ mBtManager = LocalBluetoothManager.getInstance(this);
+ mContext = this;
+
+ HandlerThread thread = new HandlerThread("DockService");
+ thread.start();
+
+ mServiceLooper = thread.getLooper();
+ mServiceHandler = new ServiceHandler(mServiceLooper);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (DEBUG) Log.d(TAG, "onDestroy");
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ mServiceLooper.quit();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // not supported
+ return null;
+ }
+
+ @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;
+ }
+
+ 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;
+ }
+
+ msg.arg2 = startId;
+ processMessage(msg);
+
+ return START_STICKY;
+ }
+
+ private final class ServiceHandler extends Handler {
+ public ServiceHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ processMessage(msg);
+ }
+ }
+
+ // This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper
+ void processMessage(Message msg) {
+ int msgType = msg.what;
+ int state = msg.arg1;
+ int startId = msg.arg2;
+ BluetoothDevice device = (BluetoothDevice) msg.obj;
+
+ if(DEBUG) Log.d(TAG, "processMessage: " + msgType + " state: " + state + " device = "
+ + (msg.obj == null ? "null" : device.toString()));
+
+ switch (msgType) {
+ case MSG_TYPE_SHOW_UI:
+ //TODO dismiss mDialog if exist? Shouldn't normally happen
+ mDevice = device;
+ createDialog(mContext, mDevice, state, startId);
+ break;
+
+ case MSG_TYPE_DOCKED:
+ 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);
+
+ if (!device.equals(mDevice)) {
+ if (mDevice != null) {
+ // Not expected. Cleanup/undock existing
+ handleUndocked(mContext, mBtManager, mDevice);
+ }
+
+ mDevice = device;
+ if (getAutoConnectSetting(mBtManager, device.getAddress())) {
+ // Setting == auto connect
+ initBtSettings(mContext, device, state, false);
+ applyBtSettings();
+ } else {
+ createDialog(mContext, mDevice, state, startId);
+ }
+ }
+ break;
+
+ case MSG_TYPE_UNDOCKED_PERMANENT:
+ // Grace period passed. Disconnect.
+ handleUndocked(mContext, mBtManager, device);
+ break;
+
+ case MSG_TYPE_UNDOCKED_TEMPORARY:
+ // Undocked event received. Queue a delayed msg to sever connection
+ Message newMsg = mServiceHandler.obtainMessage(MSG_TYPE_UNDOCKED_PERMANENT, state,
+ 0, device);
+ mServiceHandler.sendMessageDelayed(newMsg, UNDOCKED_GRACE_PERIOD);
+ break;
+ }
+
+ if (mDialog == 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(DockService.this, msg.arg1);
+ }
+ }
+
+ 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.getName()));
+ }
+
+ if (device == null) {
+ Log.e(TAG, "device is null");
+ return null;
+ }
+
+ 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_CAR:
+ if (DockEventReceiver.ACTION_DOCK_SHOW_UI.equals(intent.getAction())) {
+ msgType = MSG_TYPE_SHOW_UI;
+ } else {
+ msgType = MSG_TYPE_DOCKED;
+ }
+ break;
+ default:
+ return null;
+ }
+
+ return mServiceHandler.obtainMessage(msgType, state, 0, device);
+ }
+
+ private boolean createDialog(DockService service, BluetoothDevice device, int state,
+ int startId) {
+ switch (state) {
+ case Intent.EXTRA_DOCK_STATE_CAR:
+ case Intent.EXTRA_DOCK_STATE_DESK:
+ break;
+ default:
+ return false;
+ }
+
+ startForeground(0, new Notification());
+
+ // Device in a new dock.
+ boolean firstTime = !hasAutoConnectSetting(mBtManager, device.getAddress());
+
+ CharSequence[] items = initBtSettings(service, device, state, firstTime);
+
+ final AlertDialog.Builder ab = new AlertDialog.Builder(service);
+ ab.setTitle(service.getString(R.string.bluetooth_dock_settings_title));
+
+ // Profiles
+ ab.setMultiChoiceItems(items, mCheckedItems, service);
+
+ // Remember this settings
+ LayoutInflater inflater = (LayoutInflater) service
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ float pixelScaleFactor = service.getResources().getDisplayMetrics().density;
+ View 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 || getAutoConnectSetting(mBtManager, device.getAddress());
+ rememberCheckbox.setChecked(checked);
+ rememberCheckbox.setOnCheckedChangeListener(this);
+ int viewSpacingLeft = (int) (14 * pixelScaleFactor);
+ int viewSpacingRight = (int) (14 * pixelScaleFactor);
+ ab.setView(view, viewSpacingLeft, 0 /* top */, viewSpacingRight, 0 /* bottom */);
+ if (DEBUG) {
+ Log.d(TAG, "Auto connect = " + getAutoConnectSetting(mBtManager, device.getAddress()));
+ }
+
+ // Ok Button
+ ab.setPositiveButton(service.getString(android.R.string.ok), service);
+
+ mStartIdAssociatedWithDialog = startId;
+ mDialog = ab.create();
+ mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+ mDialog.setOnDismissListener(service);
+ mDialog.show();
+ return true;
+ }
+
+ // Called when the individual bt profiles are clicked.
+ 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
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (DEBUG) Log.d(TAG, "onCheckedChanged: Remember Settings = " + isChecked);
+ saveAutoConnectSetting(mBtManager, mDevice.getAddress(), isChecked);
+ }
+
+ // Called when the dialog is dismissed
+ 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.
+ DockEventReceiver.finishStartingService(mContext, mStartIdAssociatedWithDialog);
+ mContext.stopForeground(true);
+ }
+
+ // Called when clicked on the OK button
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ if (!hasAutoConnectSetting(mBtManager, mDevice.getAddress())) {
+ saveAutoConnectSetting(mBtManager, mDevice.getAddress(), true);
+ }
+
+ // TODO move this to a background thread
+ switch (mBtManager.getBluetoothState()) {
+ case BluetoothAdapter.STATE_OFF:
+ case BluetoothAdapter.STATE_TURNING_OFF:
+ mBtManager.getBluetoothAdapter().enable();
+ // TODO can I call connect right away? probably not.
+ break;
+ case BluetoothAdapter.STATE_TURNING_ON:
+ // TODO wait? probably
+ break;
+ case BluetoothAdapter.STATE_ON:
+ break;
+ }
+
+ applyBtSettings();
+ }
+ }
+
+ private CharSequence[] initBtSettings(DockService service, BluetoothDevice device, int state,
+ boolean firstTime) {
+ // TODO Avoid hardcoding dock and profiles. Read from system properties
+ int numOfProfiles = 0;
+ switch (state) {
+ case Intent.EXTRA_DOCK_STATE_DESK:
+ numOfProfiles = 1;
+ break;
+ case Intent.EXTRA_DOCK_STATE_CAR:
+ numOfProfiles = 2;
+ break;
+ default:
+ return null;
+ }
+
+ mProfiles = new Profile[numOfProfiles];
+ mCheckedItems = new boolean[numOfProfiles];
+ CharSequence[] items = new CharSequence[numOfProfiles];
+
+ int i = 0;
+ switch (state) {
+ case Intent.EXTRA_DOCK_STATE_CAR:
+ items[i] = service.getString(R.string.bluetooth_dock_settings_headset);
+ mProfiles[i] = Profile.HEADSET;
+ if (firstTime) {
+ mCheckedItems[i] = true;
+ } else {
+ mCheckedItems[i] = LocalBluetoothProfileManager.getProfileManager(mBtManager,
+ Profile.HEADSET).isPreferred(device);
+ }
+ ++i;
+ // fall through
+ case Intent.EXTRA_DOCK_STATE_DESK:
+ items[i] = service.getString(R.string.bluetooth_dock_settings_a2dp);
+ mProfiles[i] = Profile.A2DP;
+ if (firstTime) {
+ mCheckedItems[i] = true;
+ } else {
+ mCheckedItems[i] = LocalBluetoothProfileManager.getProfileManager(mBtManager,
+ Profile.A2DP).isPreferred(device);
+ }
+ break;
+ }
+ return items;
+ }
+
+ private void applyBtSettings() {
+ if (mProfiles == null) return;
+ for (int i = 0; i < mProfiles.length; i++) {
+ LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
+ .getProfileManager(mBtManager, mProfiles[i]);
+ boolean isConnected = profileManager.isConnected(mDevice);
+ CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(mContext, mBtManager,
+ mDevice);
+
+ if (DEBUG) Log.d(TAG, mProfiles[i].toString() + " = " + mCheckedItems[i]);
+
+ if (mCheckedItems[i] && !isConnected) {
+ // Checked but not connected
+ if (DEBUG) Log.d(TAG, "Connecting ");
+ cachedDevice.connect(mProfiles[i]);
+ } else if (!mCheckedItems[i] && isConnected) {
+ // Unchecked but connected
+ if (DEBUG) Log.d(TAG, "Disconnecting");
+ cachedDevice.disconnect(mProfiles[i]);
+ }
+ profileManager.setPreferred(mDevice, mCheckedItems[i]);
+ if (DEBUG) {
+ if (mCheckedItems[i] != LocalBluetoothProfileManager.getProfileManager(
+ mBtManager, Profile.HEADSET).isPreferred(mDevice)) {
+ Log.e(TAG, "Can't save prefered value");
+ }
+ }
+ }
+ }
+
+ void handleUndocked(Context context, LocalBluetoothManager localManager,
+ BluetoothDevice device) {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ mDevice = null;
+ CachedBluetoothDevice cachedBluetoothDevice = getCachedBluetoothDevice(context,
+ localManager, device);
+ cachedBluetoothDevice.disconnect();
+ }
+
+ void handleDocked(Context context, LocalBluetoothManager localManager,
+ BluetoothDevice device, int state) {
+ CachedBluetoothDevice cachedBluetoothDevice = getCachedBluetoothDevice(context,
+ localManager, device);
+ cachedBluetoothDevice.connect();
+ }
+
+ private static CachedBluetoothDevice getCachedBluetoothDevice(Context context,
+ LocalBluetoothManager localManager, BluetoothDevice device) {
+ CachedBluetoothDeviceManager cachedDeviceManager = localManager.getCachedDeviceManager();
+ CachedBluetoothDevice cachedBluetoothDevice = cachedDeviceManager.findDevice(device);
+ if (cachedBluetoothDevice == null) {
+ cachedBluetoothDevice = new CachedBluetoothDevice(context, device);
+ }
+ return cachedBluetoothDevice;
+ }
+
+ public static boolean hasAutoConnectSetting(LocalBluetoothManager localManager, String addr) {
+ return localManager.getSharedPreferences().contains(
+ SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK + addr);
+ }
+
+ public static boolean getAutoConnectSetting(LocalBluetoothManager localManager, String addr) {
+ return localManager.getSharedPreferences().getBoolean(
+ SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK + addr, false);
+ }
+
+ public static void saveAutoConnectSetting(LocalBluetoothManager localManager, String addr,
+ boolean autoConnect) {
+ SharedPreferences.Editor editor = localManager.getSharedPreferences().edit();
+ editor.putBoolean(SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK + addr, autoConnect);
+ editor.commit();
+ }
+
+ // TODO Delete this method if not needed.
+ private Notification getNotification(Service service) {
+ CharSequence title = service.getString(R.string.dock_settings_title);
+
+ Notification n = new Notification(R.drawable.ic_bt_headphones_a2dp, title, System
+ .currentTimeMillis());
+
+ CharSequence contentText = service.getString(R.string.dock_settings_summary);
+ Intent notificationIntent = new Intent(service, DockEventReceiver.class);
+ notificationIntent.setAction(DockEventReceiver.ACTION_DOCK_SHOW_UI);
+ PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, notificationIntent, 0);
+
+ n.setLatestEventInfo(service, title, contentText, pendingIntent);
+ return n;
+ }
+}
diff --git a/src/com/android/settings/bluetooth/DockSettingsActivity.java b/src/com/android/settings/bluetooth/DockSettingsActivity.java
deleted file mode 100644
index f5e0055..0000000
--- a/src/com/android/settings/bluetooth/DockSettingsActivity.java
+++ /dev/null
@@ -1,312 +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 com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-import com.android.settings.R;
-import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
-
-import android.app.AlertDialog;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.WindowManager;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-
-/**
- * RequestPermissionActivity asks the user whether to enable discovery. This is
- * usually started by an application wanted to start bluetooth and or discovery
- */
-public class DockSettingsActivity extends AlertActivity implements DialogInterface.OnClickListener,
- AlertDialog.OnMultiChoiceClickListener, OnCheckedChangeListener {
-
- private static final String TAG = "DockSettingsActivity";
-
- private static final boolean DEBUG = true;
-
- private static final String SHARED_PREFERENCES_KEY_AUTO_CONNECT_TO_DOCK = "auto_connect_to_dock";
-
- private BluetoothDevice mDevice;
-
- private int mState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
-
- private CachedBluetoothDevice mCachedDevice;
-
- private LocalBluetoothManager mLocalManager;
-
- private LocalBluetoothProfileManager mA2dpMgr;
-
- private LocalBluetoothProfileManager mHeadsetMgr;
-
- private LocalBluetoothProfileManager[] mProfileManagers;
-
- private boolean[] mCheckedItems;
-
- private CheckBox mRememberCheck;
-
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!parseIntent(intent)) {
- finish();
- return;
- }
-
- if (DEBUG) Log.d(TAG, "Action: " + intent.getAction() + " State: " + mState);
- }
- };
-
- private Profile[] mProfiles;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (!parseIntent(getIntent())) {
- finish();
- return;
- }
-
- if (mState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- handleUndocked(this, mLocalManager, mDevice);
- dismiss();
- return;
- }
- getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
- createDialog();
- getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- if (!parseIntent(getIntent())) {
- finish();
- return;
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- IntentFilter filter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
- registerReceiver(mReceiver, filter);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mReceiver);
- }
-
- private void createDialog() {
- // TODO Avoid hardcoding dock and profiles. Read from system properties
- int numOfProfiles;
- switch (mState) {
- case Intent.EXTRA_DOCK_STATE_CAR:
- numOfProfiles = 2;
- break;
- case Intent.EXTRA_DOCK_STATE_DESK:
- numOfProfiles = 1;
- break;
- default:
- return;
- }
-
- CharSequence[] items = new CharSequence[numOfProfiles];
- mCheckedItems = new boolean[numOfProfiles];
- mProfileManagers = new LocalBluetoothProfileManager[numOfProfiles];
- mProfiles = new Profile[numOfProfiles];
-
- int i = 0;
- switch (mState) {
- case Intent.EXTRA_DOCK_STATE_CAR:
- mProfileManagers[i] = mHeadsetMgr;
- mProfiles[i] = Profile.HEADSET;
- mCheckedItems[i] = mHeadsetMgr.isPreferred(mDevice);
- items[i] = getString(R.string.bluetooth_dock_settings_headset);
- ++i;
- // fall through
- case Intent.EXTRA_DOCK_STATE_DESK:
- mProfileManagers[i] = mA2dpMgr;
- mProfiles[i] = Profile.A2DP;
- mCheckedItems[i] = mA2dpMgr.isPreferred(mDevice);
- items[i] = getString(R.string.bluetooth_dock_settings_a2dp);
- break;
- }
-
- final AlertController.AlertParams p = mAlertParams;
- p.mTitle = getString(R.string.bluetooth_dock_settings_title);
-
- // Profiles
- p.mIsMultiChoice = true;
- p.mItems = items;
- p.mCheckedItems = mCheckedItems;
- p.mOnCheckboxClickListener = this;
-
- // Remember this settings
- LayoutInflater inflater = (LayoutInflater) getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- p.mView = inflater.inflate(R.layout.remember_dock_setting, null);
- p.mViewSpacingSpecified = true;
- float pixelScaleFactor = getResources().getDisplayMetrics().density;
- p.mViewSpacingLeft = (int) (14 * pixelScaleFactor);
- p.mViewSpacingRight = (int) (14 * pixelScaleFactor);
- mRememberCheck = (CheckBox)p.mView.findViewById(R.id.remember);
- if (DEBUG) Log.d(TAG, "Auto Check? = " + getAutoConnectSetting(mLocalManager));
- mRememberCheck.setChecked(getAutoConnectSetting(mLocalManager));
- mRememberCheck.setOnCheckedChangeListener(this);
-
- // Ok Button
- p.mPositiveButtonText = getString(android.R.string.ok);
- p.mPositiveButtonListener = this;
-
- setupAlert();
- }
-
- // Called when the individual items are clicked.
- 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
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (DEBUG) Log.d(TAG, "onCheckedChanged: Remember Settings = " + isChecked);
- saveAutoConnectSetting(mLocalManager, isChecked);
- }
-
- // Called when clicked on the OK button
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- switch (mLocalManager.getBluetoothState()) {
- case BluetoothAdapter.STATE_OFF:
- case BluetoothAdapter.STATE_TURNING_OFF:
- mLocalManager.getBluetoothAdapter().enable();
- // TODO can I call connect right away? probably not.
- break;
- case BluetoothAdapter.STATE_TURNING_ON:
- // TODO wait? probably
- break;
- case BluetoothAdapter.STATE_ON:
- break;
- }
-
- for(int i = 0; i < mProfileManagers.length; i++) {
- mProfileManagers[i].setPreferred(mDevice, mCheckedItems[i]);
-
- if (DEBUG) Log.d(TAG, mProfileManagers[i].toString() + " = " + mCheckedItems[i]);
- boolean isConnected = mProfileManagers[i].isConnected(mDevice);
- if (mCheckedItems[i] && !isConnected) {
- if (DEBUG) Log.d(TAG, "Connecting ");
- mCachedDevice.connect(mProfiles[i]);
- } else if (isConnected){
- if (DEBUG) Log.d(TAG, "Disconnecting");
- mProfileManagers[i].disconnect(mDevice);
- }
- }
- }
- }
-
- private boolean parseIntent(Intent intent) {
- if (intent == null) {
- return false;
- }
-
- mLocalManager = LocalBluetoothManager.getInstance(this);
- if (mLocalManager == null) {
- if (DEBUG) Log.d(TAG, "Error: there's a problem starting bluetooth");
- return false;
- }
-
- mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (mDevice == null) {
- if (DEBUG) Log.d(TAG, "device == null");
- return false;
- }
-
- mState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
- if (mState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- handleUndocked(this, mLocalManager, mDevice);
- return false;
- }
-
- mCachedDevice = getCachedBluetoothDevice(this, mLocalManager, mDevice);
- mA2dpMgr = LocalBluetoothProfileManager.getProfileManager(mLocalManager, Profile.A2DP);
- mHeadsetMgr = LocalBluetoothProfileManager.getProfileManager(mLocalManager,
- Profile.HEADSET);
-
- return true;
- }
-
- public static void handleUndocked(Context context, LocalBluetoothManager localManager,
- BluetoothDevice device) {
- CachedBluetoothDevice cachedBluetoothDevice = getCachedBluetoothDevice(context,
- localManager, device);
- cachedBluetoothDevice.disconnect();
- }
-
- public static void handleDocked(Context context, LocalBluetoothManager localManager,
- BluetoothDevice device, int state) {
- CachedBluetoothDevice cachedBluetoothDevice = getCachedBluetoothDevice(context,
- localManager, device);
- cachedBluetoothDevice.connect();
- }
-
- private static CachedBluetoothDevice getCachedBluetoothDevice(Context context,
- LocalBluetoothManager localManager, BluetoothDevice device) {
- CachedBluetoothDeviceManager cachedDeviceManager = localManager.getCachedDeviceManager();
- CachedBluetoothDevice cachedBluetoothDevice = cachedDeviceManager.findDevice(device);
- if (cachedBluetoothDevice == null) {
- cachedBluetoothDevice = new CachedBluetoothDevice(context, device);
- }
- return cachedBluetoothDevice;
- }
-
- public static boolean hasAutoConnectSetting(LocalBluetoothManager localManager) {
- return localManager.getSharedPreferences().contains(
- SHARED_PREFERENCES_KEY_AUTO_CONNECT_TO_DOCK);
- }
-
- public static boolean getAutoConnectSetting(LocalBluetoothManager localManager) {
- return localManager.getSharedPreferences().getBoolean(
- SHARED_PREFERENCES_KEY_AUTO_CONNECT_TO_DOCK, false);
- }
-
- public static void saveAutoConnectSetting(LocalBluetoothManager localManager,
- boolean autoConnect) {
- SharedPreferences.Editor editor = localManager.getSharedPreferences().edit();
- editor.putBoolean(SHARED_PREFERENCES_KEY_AUTO_CONNECT_TO_DOCK, autoConnect);
- editor.commit();
- }
-}