• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.bluetooth;
18 
19 import android.app.Service;
20 import android.bluetooth.BluetoothA2dp;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothHeadset;
24 import android.bluetooth.BluetoothProfile;
25 import android.content.BroadcastReceiver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.os.PowerManager;
29 import android.util.Log;
30 
31 public final class DockEventReceiver extends BroadcastReceiver {
32 
33     private static final boolean DEBUG = DockService.DEBUG;
34 
35     private static final String TAG = "DockEventReceiver";
36 
37     public static final String ACTION_DOCK_SHOW_UI =
38         "com.android.settings.bluetooth.action.DOCK_SHOW_UI";
39 
40     private static final int EXTRA_INVALID = -1234;
41 
42     private static final Object sStartingServiceSync = new Object();
43 
44     private static PowerManager.WakeLock sStartingService;
45 
46     @Override
onReceive(Context context, Intent intent)47     public void onReceive(Context context, Intent intent) {
48         if (intent == null)
49             return;
50 
51         int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, intent.getIntExtra(
52                 BluetoothAdapter.EXTRA_STATE, EXTRA_INVALID));
53         BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
54 
55         if (DEBUG) {
56             Log.d(TAG, "Action: " + intent.getAction() + " State:" + state + " Device: "
57                     + (device == null ? "null" : device.getAliasName()));
58         }
59 
60         if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())
61                 || ACTION_DOCK_SHOW_UI.endsWith(intent.getAction())) {
62             if (device == null) {
63                 if (DEBUG) Log.d(TAG, "Device is missing");
64                 return;
65             }
66 
67             switch (state) {
68                 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
69                 case Intent.EXTRA_DOCK_STATE_CAR:
70                 case Intent.EXTRA_DOCK_STATE_DESK:
71                 case Intent.EXTRA_DOCK_STATE_LE_DESK:
72                 case Intent.EXTRA_DOCK_STATE_HE_DESK:
73                     Intent i = new Intent(intent);
74                     i.setClass(context, DockService.class);
75                     beginStartingService(context, i);
76                     break;
77                 default:
78                     Log.e(TAG, "Unknown state: " + state);
79                     break;
80             }
81         } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction()) ||
82                    BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
83             int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
84                     BluetoothProfile.STATE_CONNECTED);
85             int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
86 
87             /*
88              *  Reconnect to the dock if:
89              *  1) it is a dock
90              *  2) it is disconnected
91              *  3) the disconnect is initiated remotely
92              *  4) the dock is still docked (check can only be done in the Service)
93              */
94             if (device == null) {
95                 if (DEBUG) Log.d(TAG, "Device is missing");
96                 return;
97             }
98 
99             if (newState == BluetoothProfile.STATE_DISCONNECTED &&
100                     oldState != BluetoothProfile.STATE_DISCONNECTING) {
101                 // Too bad, the dock state can't be checked from a BroadcastReceiver.
102                 Intent i = new Intent(intent);
103                 i.setClass(context, DockService.class);
104                 beginStartingService(context, i);
105             }
106 
107         } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
108             int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
109             if (btState != BluetoothAdapter.STATE_TURNING_ON) {
110                 Intent i = new Intent(intent);
111                 i.setClass(context, DockService.class);
112                 beginStartingService(context, i);
113             }
114         }
115     }
116 
117     /**
118      * Start the service to process the current event notifications, acquiring
119      * the wake lock before returning to ensure that the service will run.
120      */
beginStartingService(Context context, Intent intent)121     private static void beginStartingService(Context context, Intent intent) {
122         synchronized (sStartingServiceSync) {
123             if (sStartingService == null) {
124                 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
125                 sStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
126                         "StartingDockService");
127             }
128 
129             sStartingService.acquire();
130 
131             if (context.startService(intent) == null) {
132                 Log.e(TAG, "Can't start DockService");
133             }
134         }
135     }
136 
137     /**
138      * Called back by the service when it has finished processing notifications,
139      * releasing the wake lock if the service is now stopping.
140      */
finishStartingService(Service service, int startId)141     public static void finishStartingService(Service service, int startId) {
142         synchronized (sStartingServiceSync) {
143             if (sStartingService != null) {
144                 if (DEBUG) Log.d(TAG, "stopSelf id = " + startId);
145                 if (service.stopSelfResult(startId)) {
146                     Log.d(TAG, "finishStartingService: stopping service");
147                     sStartingService.release();
148                 }
149             }
150         }
151     }
152 }
153