A2dpService.java revision 3fafe61ef25c1899fdc817c52163aec16c31055c
1/*
2 * Copyright (C) 2012 Google Inc.
3 */
4package com.android.bluetooth.a2dp;
5
6import android.app.Service;
7import android.bluetooth.BluetoothAdapter;
8import android.bluetooth.BluetoothDevice;
9import android.bluetooth.BluetoothProfile;
10import android.bluetooth.IBluetoothA2dp;
11import android.content.BroadcastReceiver;
12import android.content.Context;
13import android.content.Intent;
14import android.os.Handler;
15import android.os.IBinder;
16import android.os.Message;
17import android.provider.Settings;
18import android.util.Log;
19import java.util.List;
20import java.util.Iterator;
21import java.util.Map;
22import android.content.pm.PackageManager;
23import com.android.bluetooth.btservice.AdapterService;
24
25/**
26 * Provides Bluetooth A2DP profile, as a service in the Bluetooth application.
27 * @hide
28 */
29public class A2dpService extends Service {
30    private static final String TAG = "BluetoothA2dpService";
31    private static final boolean DBG = true;
32
33    static final String BLUETOOTH_ADMIN_PERM =
34        android.Manifest.permission.BLUETOOTH_ADMIN;
35    static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
36
37    private BluetoothAdapter mAdapter;
38    private A2dpStateMachine mStateMachine;
39
40    @Override
41    public void onCreate() {
42        log("onCreate");
43        super.onCreate();
44        mAdapter = BluetoothAdapter.getDefaultAdapter();
45    }
46
47    @Override
48    public IBinder onBind(Intent intent) {
49        log("onBind");
50        return mBinder;
51    }
52
53    public void onStart(Intent intent, int startId) {
54        log("onStart");
55
56        if (mAdapter == null) {
57            Log.w(TAG, "Stopping profile service: device does not have BT");
58            stop();
59        }
60
61        if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) {
62            Log.e(TAG, "Permission denied!");
63            return;
64        }
65
66        String action = intent.getStringExtra(AdapterService.EXTRA_ACTION);
67        if (!AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
68            Log.e(TAG, "Invalid action " + action);
69            return;
70        }
71
72        int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
73        if(state==BluetoothAdapter.STATE_OFF) {
74            stop();
75        } else if (state== BluetoothAdapter.STATE_ON){
76            start();
77        }
78    }
79
80    @Override
81    public void onDestroy() {
82        super.onDestroy();
83        if (DBG) log("Destroying service.");
84        if(mAdapter != null)
85            mAdapter = null;
86    }
87
88   private void start() {
89        if (DBG) log("startService()");
90        mStateMachine = new A2dpStateMachine(this);
91        mStateMachine.start();
92
93        //Notify adapter service
94        AdapterService sAdapter = AdapterService.getAdapterService();
95        if (sAdapter!= null) {
96            sAdapter.onProfileServiceStateChanged(getClass().getName(), BluetoothAdapter.STATE_ON);
97        }
98    }
99
100    private void stop() {
101        if (DBG) log("stopService()");
102        if (mStateMachine!= null) {
103            mStateMachine.quit();
104            mStateMachine.cleanup();
105            mStateMachine=null;
106        }
107
108        //Notify adapter service
109        AdapterService sAdapter = AdapterService.getAdapterService();
110        if (sAdapter!= null) {
111            sAdapter.onProfileServiceStateChanged(getClass().getName(), BluetoothAdapter.STATE_OFF);
112        }
113        stopSelf();
114    }
115
116    /**
117     * Handlers for incoming service calls
118     */
119    private final IBluetoothA2dp.Stub mBinder = new IBluetoothA2dp.Stub() {
120
121        public boolean connect(BluetoothDevice device) {
122            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
123                                           "Need BLUETOOTH ADMIN permission");
124
125            if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
126                return false;
127            }
128
129            int connectionState = mStateMachine.getConnectionState(device);
130            if (connectionState == BluetoothProfile.STATE_CONNECTED ||
131                connectionState == BluetoothProfile.STATE_CONNECTING) {
132                return false;
133            }
134
135            mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
136            return true;
137        }
138
139        public boolean disconnect(BluetoothDevice device) {
140            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
141                                           "Need BLUETOOTH ADMIN permission");
142            int connectionState = mStateMachine.getConnectionState(device);
143            if (connectionState != BluetoothProfile.STATE_CONNECTED &&
144                connectionState != BluetoothProfile.STATE_CONNECTING) {
145                return false;
146            }
147
148            mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device);
149            return true;
150        }
151
152        public List<BluetoothDevice> getConnectedDevices() {
153            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
154            return mStateMachine.getConnectedDevices();
155        }
156
157        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
158            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
159            return mStateMachine.getDevicesMatchingConnectionStates(states);
160        }
161
162        public int getConnectionState(BluetoothDevice device) {
163            enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
164            return mStateMachine.getConnectionState(device);
165        }
166
167        public boolean setPriority(BluetoothDevice device, int priority) {
168            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
169                                           "Need BLUETOOTH_ADMIN permission");
170            Settings.Secure.putInt(getContentResolver(),
171                Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
172                priority);
173            if (DBG) log("Saved priority " + device + " = " + priority);
174            return true;
175        }
176
177        public int getPriority(BluetoothDevice device) {
178            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
179                                           "Need BLUETOOTH_ADMIN permission");
180            int priority = Settings.Secure.getInt(getContentResolver(),
181                Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
182                BluetoothProfile.PRIORITY_UNDEFINED);
183            return priority;
184        }
185
186        public synchronized boolean isA2dpPlaying(BluetoothDevice device) {
187            enforceCallingOrSelfPermission(BLUETOOTH_PERM,
188                                           "Need BLUETOOTH permission");
189            if (DBG) log("isA2dpPlaying(" + device + ")");
190            return mStateMachine.isPlaying(device);
191        }
192    };
193
194    private static void log(String msg) {
195        Log.d(TAG, msg);
196    }
197}
198