A2dpProfile.java revision afedeacd575d51edc4f741bd2c8f75dd4928f2b6
1/*
2 * Copyright (C) 2011 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
17package com.android.settings.bluetooth;
18
19import android.bluetooth.BluetoothA2dp;
20import android.bluetooth.BluetoothAdapter;
21import android.bluetooth.BluetoothClass;
22import android.bluetooth.BluetoothDevice;
23import android.bluetooth.BluetoothProfile;
24import android.bluetooth.BluetoothUuid;
25import android.content.Context;
26import android.os.ParcelUuid;
27import android.util.Log;
28
29import com.android.settings.R;
30
31import java.util.ArrayList;
32import java.util.List;
33
34final class A2dpProfile implements LocalBluetoothProfile {
35    private static final String TAG = "A2dpProfile";
36    private static boolean V = true;
37
38    private BluetoothA2dp mService;
39    private boolean mIsProfileReady;
40
41    static final ParcelUuid[] SINK_UUIDS = {
42        BluetoothUuid.AudioSink,
43        BluetoothUuid.AdvAudioDist,
44    };
45
46    static final String NAME = "A2DP";
47    private final LocalBluetoothProfileManager mProfileManager;
48
49    // Order of this profile in device profiles list
50    private static final int ORDINAL = 1;
51
52    // These callbacks run on the main thread.
53    private final class A2dpServiceListener
54            implements BluetoothProfile.ServiceListener {
55
56        public void onServiceConnected(int profile, BluetoothProfile proxy) {
57            if (V) Log.d(TAG,"Bluetooth service connected");
58            mService = (BluetoothA2dp) proxy;
59            mProfileManager.setA2dpServiceUp(true);
60            mIsProfileReady=true;
61        }
62
63        public void onServiceDisconnected(int profile) {
64            if (V) Log.d(TAG,"Bluetooth service disconnected");
65            mProfileManager.setA2dpServiceUp(false);
66            mIsProfileReady=false;
67        }
68    }
69
70    public boolean isProfileReady() {
71        return mIsProfileReady;
72    }
73    A2dpProfile(Context context, LocalBluetoothProfileManager profileManager) {
74        mProfileManager = profileManager;
75        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
76        adapter.getProfileProxy(context, new A2dpServiceListener(),
77                BluetoothProfile.A2DP);
78    }
79
80    public boolean isConnectable() {
81        return true;
82    }
83
84    public boolean isAutoConnectable() {
85        return true;
86    }
87
88    public List<BluetoothDevice> getConnectedDevices() {
89        if (mService == null) return new ArrayList<BluetoothDevice>(0);
90        return mService.getDevicesMatchingConnectionStates(
91              new int[] {BluetoothProfile.STATE_CONNECTED,
92                         BluetoothProfile.STATE_CONNECTING,
93                         BluetoothProfile.STATE_DISCONNECTING});
94    }
95
96    public boolean connect(BluetoothDevice device) {
97        if (mService == null) return false;
98        List<BluetoothDevice> sinks = getConnectedDevices();
99        if (sinks != null) {
100            for (BluetoothDevice sink : sinks) {
101                mService.disconnect(sink);
102            }
103        }
104        return mService.connect(device);
105    }
106
107    public boolean disconnect(BluetoothDevice device) {
108        if (mService == null) return false;
109        return mService.disconnect(device);
110    }
111
112    // This function is added as the AUTO CONNECT priority could not be set by using setPreferred(),
113    // as setPreferred() takes only boolean input but getPreferred() supports interger output.
114    // Also this need not implemented by all profiles so this has been added here.
115    public void enableAutoConnect(BluetoothDevice device, boolean enable) {
116        if (mService == null) return;
117        if (enable) {
118             mService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT);
119        } else {
120             if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
121                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
122             }
123        }
124    }
125
126    public int getConnectionStatus(BluetoothDevice device) {
127        if (mService == null) {
128            return BluetoothProfile.STATE_DISCONNECTED;
129        }
130        return mService.getConnectionState(device);
131    }
132
133    public boolean isPreferred(BluetoothDevice device) {
134        if (mService == null) return false;
135        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
136    }
137
138    public int getPreferred(BluetoothDevice device) {
139        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
140        return mService.getPriority(device);
141    }
142
143    public void setPreferred(BluetoothDevice device, boolean preferred) {
144        if (mService == null) return;
145        if (preferred) {
146            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
147                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
148            }
149        } else {
150            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
151        }
152    }
153
154    boolean isA2dpPlaying() {
155        if (mService == null) return false;
156        List<BluetoothDevice> sinks = mService.getConnectedDevices();
157        if (!sinks.isEmpty()) {
158            if (mService.isA2dpPlaying(sinks.get(0))) {
159                return true;
160            }
161        }
162        return false;
163    }
164
165    public String toString() {
166        return NAME;
167    }
168
169    public int getOrdinal() {
170        return ORDINAL;
171    }
172
173    public int getNameResource(BluetoothDevice device) {
174        return R.string.bluetooth_profile_a2dp;
175    }
176
177    public int getSummaryResourceForDevice(BluetoothDevice device) {
178        int state = getConnectionStatus(device);
179        switch (state) {
180            case BluetoothProfile.STATE_DISCONNECTED:
181            {
182                setPreferred(device, false);
183                return R.string.bluetooth_a2dp_profile_summary_use_for;
184            }
185            case BluetoothProfile.STATE_CONNECTED:
186            {
187                setPreferred(device, true);
188                return R.string.bluetooth_a2dp_profile_summary_connected;
189            }
190            default:
191                return Utils.getConnectionStateSummary(state);
192        }
193    }
194
195    public int getDrawableResource(BluetoothClass btClass) {
196        return R.drawable.ic_bt_headphones_a2dp;
197    }
198
199    protected void finalize() {
200        if (V) Log.d(TAG, "finalize()");
201        if (mService != null) {
202            try {
203                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP, mService);
204                mService = null;
205            }catch (Throwable t) {
206                Log.w(TAG, "Error cleaning up A2DP proxy", t);
207            }
208        }
209    }
210}
211