DockEventReceiver.java revision 5809d33296d60f54c7e93de2f45bd84579f70449
1df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan/* 2df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Copyright (C) 2009 The Android Open Source Project 3df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * 4df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 5df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * you may not use this file except in compliance with the License. 6df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * You may obtain a copy of the License at 7df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * 8df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * http://www.apache.org/licenses/LICENSE-2.0 9df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * 10df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Unless required by applicable law or agreed to in writing, software 11df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, 12df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * See the License for the specific language governing permissions and 14df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * limitations under the License. 15df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan */ 16df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 17df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanpackage com.android.settings.bluetooth; 18df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 19732c1dad5a4871597652f17986b7a602897e5a76Michael Chanimport com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile; 20732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 21df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.app.Service; 22732c1dad5a4871597652f17986b7a602897e5a76Michael Chanimport android.bluetooth.BluetoothA2dp; 23fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chanimport android.bluetooth.BluetoothAdapter; 24df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.bluetooth.BluetoothDevice; 25732c1dad5a4871597652f17986b7a602897e5a76Michael Chanimport android.bluetooth.BluetoothHeadset; 265809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganeshimport android.bluetooth.BluetoothProfile; 27df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.content.BroadcastReceiver; 28df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.content.Context; 29df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.content.Intent; 30732c1dad5a4871597652f17986b7a602897e5a76Michael Chanimport android.content.IntentFilter; 31df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.os.PowerManager; 32df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.util.Log; 33df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 34df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanpublic class DockEventReceiver extends BroadcastReceiver { 35df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 36845e740fc63657438b9085376c8e7d60d8334a72Michael Chan private static final boolean DEBUG = DockService.DEBUG; 37df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 38df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final String TAG = "DockEventReceiver"; 39df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 40df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public static final String ACTION_DOCK_SHOW_UI = 41df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan "com.android.settings.bluetooth.action.DOCK_SHOW_UI"; 42df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 43df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final int EXTRA_INVALID = -1234; 44df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 45fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan private static final Object mStartingServiceSync = new Object(); 46df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 47fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan private static final long WAKELOCK_TIMEOUT = 5000; 48fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan 49fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan private static PowerManager.WakeLock mStartingService; 50df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 51df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan @Override 52df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public void onReceive(Context context, Intent intent) { 53df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (intent == null) 54df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return; 55df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 563fe86a346cdcd41fd9498591571d8b512a130240Michael Chan int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, intent.getIntExtra( 573fe86a346cdcd41fd9498591571d8b512a130240Michael Chan BluetoothAdapter.EXTRA_STATE, EXTRA_INVALID)); 58df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 59df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 60df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) { 61df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan Log.d(TAG, "Action: " + intent.getAction() + " State:" + state + " Device: " 62df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan + (device == null ? "null" : device.getName())); 63df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 64df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 65df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction()) 66df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan || ACTION_DOCK_SHOW_UI.endsWith(intent.getAction())) { 67df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (device == null) { 68503c236db541b3d7c8278fa63afe4d1b792ac9a9Michael Chan if (DEBUG) Log.d(TAG, "Device is missing"); 69df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return; 70df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 71df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 72df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan switch (state) { 73df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_UNDOCKED: 74df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_CAR: 75df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_DESK: 76df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan Intent i = new Intent(intent); 77df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan i.setClass(context, DockService.class); 78df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan beginStartingService(context, i); 79df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 80df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan default: 81df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) Log.e(TAG, "Unknown state"); 82df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 83df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 845809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction()) || 855809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) { 865809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 875809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh BluetoothProfile.STATE_CONNECTED); 885809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0); 895809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh 90732c1dad5a4871597652f17986b7a602897e5a76Michael Chan /* 91732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * Reconnect to the dock if: 92732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * 1) it is a dock 93732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * 2) it is disconnected 94732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * 3) the disconnect is initiated remotely 95732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * 4) the dock is still docked (check can only be done in the Service) 96732c1dad5a4871597652f17986b7a602897e5a76Michael Chan */ 97732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (device == null) { 98732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (DEBUG) Log.d(TAG, "Device is missing"); 99732c1dad5a4871597652f17986b7a602897e5a76Michael Chan return; 100732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 101732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 1025809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh if (newState == BluetoothProfile.STATE_DISCONNECTED && 1035809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh oldState != BluetoothProfile.STATE_DISCONNECTING) { 104732c1dad5a4871597652f17986b7a602897e5a76Michael Chan // Too bad, the dock state can't be checked from a BroadcastReceiver. 105732c1dad5a4871597652f17986b7a602897e5a76Michael Chan Intent i = new Intent(intent); 106732c1dad5a4871597652f17986b7a602897e5a76Michael Chan i.setClass(context, DockService.class); 107732c1dad5a4871597652f17986b7a602897e5a76Michael Chan beginStartingService(context, i); 108732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 109732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 110845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) { 111845e740fc63657438b9085376c8e7d60d8334a72Michael Chan int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 1123fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if (btState != BluetoothAdapter.STATE_TURNING_ON) { 113845e740fc63657438b9085376c8e7d60d8334a72Michael Chan Intent i = new Intent(intent); 114845e740fc63657438b9085376c8e7d60d8334a72Michael Chan i.setClass(context, DockService.class); 115845e740fc63657438b9085376c8e7d60d8334a72Michael Chan beginStartingService(context, i); 116845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } 117df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 118df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 119df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 120df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan /** 121df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Start the service to process the current event notifications, acquiring 122df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * the wake lock before returning to ensure that the service will run. 123df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan */ 124df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public static void beginStartingService(Context context, Intent intent) { 125df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan synchronized (mStartingServiceSync) { 126df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (mStartingService == null) { 127df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 128df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 129df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan "StartingDockService"); 130df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 131df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 132fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan mStartingService.acquire(WAKELOCK_TIMEOUT); 133df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 134df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (context.startService(intent) == null) { 135df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan Log.e(TAG, "Can't start DockService"); 136df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 137df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 138df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 139df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 140df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan /** 141df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Called back by the service when it has finished processing notifications, 142df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * releasing the wake lock if the service is now stopping. 143df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan */ 144df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public static void finishStartingService(Service service, int startId) { 145df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan synchronized (mStartingServiceSync) { 146df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (mStartingService != null) { 147146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan if (DEBUG) Log.d(TAG, "stopSelf id = "+ startId); 148fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan service.stopSelfResult(startId); 149df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 150df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 151df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 152df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan} 153