MapClientProfile.java revision 631768d81469f83552de05bf0ec839d1cd6eab04
1/*
2 * Copyright (C) 2012 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.settingslib.bluetooth;
18
19import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothClass;
21import android.bluetooth.BluetoothDevice;
22import android.bluetooth.BluetoothMapClient;
23import android.bluetooth.BluetoothProfile;
24import android.bluetooth.BluetoothUuid;
25import android.content.Context;
26import android.os.ParcelUuid;
27import android.util.Log;
28
29import com.android.settingslib.R;
30
31import java.util.ArrayList;
32import java.util.List;
33
34/**
35 * MapClientProfile handles Bluetooth MAP profile.
36 */
37public final class MapClientProfile implements LocalBluetoothProfile {
38    private static final String TAG = "MapClientProfile";
39    private static boolean V = false;
40
41    private BluetoothMapClient mService;
42    private boolean mIsProfileReady;
43
44    private final LocalBluetoothAdapter mLocalAdapter;
45    private final CachedBluetoothDeviceManager mDeviceManager;
46    private final LocalBluetoothProfileManager mProfileManager;
47
48    static final ParcelUuid[] UUIDS = {
49        BluetoothUuid.MAP,
50        BluetoothUuid.MNS,
51        BluetoothUuid.MAS,
52    };
53
54    static final String NAME = "MAP Client";
55
56    // Order of this profile in device profiles list
57    private static final int ORDINAL = 0;
58
59    // These callbacks run on the main thread.
60    private final class MapClientServiceListener
61            implements BluetoothProfile.ServiceListener {
62
63        public void onServiceConnected(int profile, BluetoothProfile proxy) {
64            if (V) Log.d(TAG,"Bluetooth service connected");
65            mService = (BluetoothMapClient) proxy;
66            // We just bound to the service, so refresh the UI for any connected MAP devices.
67            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
68            while (!deviceList.isEmpty()) {
69                BluetoothDevice nextDevice = deviceList.remove(0);
70                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
71                // we may add a new device here, but generally this should not happen
72                if (device == null) {
73                    Log.w(TAG, "MapProfile found new device: " + nextDevice);
74                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
75                }
76                device.onProfileStateChanged(MapClientProfile.this,
77                        BluetoothProfile.STATE_CONNECTED);
78                device.refresh();
79            }
80
81            mProfileManager.callServiceConnectedListeners();
82            mIsProfileReady=true;
83        }
84
85        public void onServiceDisconnected(int profile) {
86            if (V) Log.d(TAG,"Bluetooth service disconnected");
87            mProfileManager.callServiceDisconnectedListeners();
88            mIsProfileReady=false;
89        }
90    }
91
92    public boolean isProfileReady() {
93        if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
94        return mIsProfileReady;
95    }
96
97    MapClientProfile(Context context, LocalBluetoothAdapter adapter,
98            CachedBluetoothDeviceManager deviceManager,
99            LocalBluetoothProfileManager profileManager) {
100        mLocalAdapter = adapter;
101        mDeviceManager = deviceManager;
102        mProfileManager = profileManager;
103        mLocalAdapter.getProfileProxy(context, new MapClientServiceListener(),
104                BluetoothProfile.MAP_CLIENT);
105    }
106
107    public boolean isConnectable() {
108        return true;
109    }
110
111    public boolean isAutoConnectable() {
112        return true;
113    }
114
115    public boolean connect(BluetoothDevice device) {
116        if (mService == null) return false;
117        List<BluetoothDevice> connectedDevices = getConnectedDevices();
118        if (connectedDevices != null) {
119            for (BluetoothDevice connectedDevice : connectedDevices) {
120                mService.disconnect(connectedDevice);
121            }
122        }
123        return mService.connect(device);
124    }
125
126    public boolean disconnect(BluetoothDevice device) {
127        if (mService == null) return false;
128        // Downgrade priority as user is disconnecting.
129        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
130            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
131        }
132        return mService.disconnect(device);
133    }
134
135    public int getConnectionStatus(BluetoothDevice device) {
136        if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
137
138        return mService.getConnectionState(device);
139    }
140
141    public boolean isPreferred(BluetoothDevice device) {
142        if (mService == null) return false;
143        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
144    }
145
146    public int getPreferred(BluetoothDevice device) {
147        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
148        return mService.getPriority(device);
149    }
150
151    public void setPreferred(BluetoothDevice device, boolean preferred) {
152        if (mService == null) return;
153        if (preferred) {
154            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
155                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
156            }
157        } else {
158            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
159        }
160    }
161
162    public List<BluetoothDevice> getConnectedDevices() {
163        if (mService == null) return new ArrayList<BluetoothDevice>(0);
164        return mService.getDevicesMatchingConnectionStates(
165              new int[] {BluetoothProfile.STATE_CONNECTED,
166                         BluetoothProfile.STATE_CONNECTING,
167                         BluetoothProfile.STATE_DISCONNECTING});
168    }
169
170    public String toString() {
171        return NAME;
172    }
173
174    public int getOrdinal() {
175        return ORDINAL;
176    }
177
178    public int getNameResource(BluetoothDevice device) {
179        return R.string.bluetooth_profile_map;
180    }
181
182    public int getSummaryResourceForDevice(BluetoothDevice device) {
183        int state = getConnectionStatus(device);
184        switch (state) {
185            case BluetoothProfile.STATE_DISCONNECTED:
186                return R.string.bluetooth_map_profile_summary_use_for;
187
188            case BluetoothProfile.STATE_CONNECTED:
189                return R.string.bluetooth_map_profile_summary_connected;
190
191            default:
192                return Utils.getConnectionStateSummary(state);
193        }
194    }
195
196    public int getDrawableResource(BluetoothClass btClass) {
197        return R.drawable.ic_bt_cellphone;
198    }
199
200    protected void finalize() {
201        if (V) Log.d(TAG, "finalize()");
202        if (mService != null) {
203            try {
204                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
205                                                                       mService);
206                mService = null;
207            }catch (Throwable t) {
208                Log.w(TAG, "Error cleaning up MAP Client proxy", t);
209            }
210        }
211    }
212}
213