blob: 95139a1bfab9cc140f1e0952459cf7a110c6288d [file] [log] [blame]
Joseph Pirozzo631768d2016-09-01 14:19:28 -07001/*
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/**
Chienyuan8862bfb2018-09-17 10:54:37 +080035 * MapClientProfile handles the Bluetooth MAP MCE role.
Joseph Pirozzo631768d2016-09-01 14:19:28 -070036 */
37public final class MapClientProfile implements LocalBluetoothProfile {
38 private static final String TAG = "MapClientProfile";
Joseph Pirozzo631768d2016-09-01 14:19:28 -070039
40 private BluetoothMapClient mService;
41 private boolean mIsProfileReady;
42
Joseph Pirozzo631768d2016-09-01 14:19:28 -070043 private final CachedBluetoothDeviceManager mDeviceManager;
44 private final LocalBluetoothProfileManager mProfileManager;
45
46 static final ParcelUuid[] UUIDS = {
47 BluetoothUuid.MAP,
48 BluetoothUuid.MNS,
49 BluetoothUuid.MAS,
50 };
51
52 static final String NAME = "MAP Client";
53
54 // Order of this profile in device profiles list
55 private static final int ORDINAL = 0;
56
57 // These callbacks run on the main thread.
58 private final class MapClientServiceListener
59 implements BluetoothProfile.ServiceListener {
60
61 public void onServiceConnected(int profile, BluetoothProfile proxy) {
Joseph Pirozzo631768d2016-09-01 14:19:28 -070062 mService = (BluetoothMapClient) proxy;
63 // We just bound to the service, so refresh the UI for any connected MAP devices.
64 List<BluetoothDevice> deviceList = mService.getConnectedDevices();
65 while (!deviceList.isEmpty()) {
66 BluetoothDevice nextDevice = deviceList.remove(0);
67 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
68 // we may add a new device here, but generally this should not happen
69 if (device == null) {
70 Log.w(TAG, "MapProfile found new device: " + nextDevice);
timhypengf64f6902018-07-31 15:40:15 +080071 device = mDeviceManager.addDevice(nextDevice);
Joseph Pirozzo631768d2016-09-01 14:19:28 -070072 }
73 device.onProfileStateChanged(MapClientProfile.this,
74 BluetoothProfile.STATE_CONNECTED);
75 device.refresh();
76 }
77
78 mProfileManager.callServiceConnectedListeners();
79 mIsProfileReady=true;
80 }
81
82 public void onServiceDisconnected(int profile) {
Joseph Pirozzo631768d2016-09-01 14:19:28 -070083 mProfileManager.callServiceDisconnectedListeners();
84 mIsProfileReady=false;
85 }
86 }
87
88 public boolean isProfileReady() {
Chienyuan8862bfb2018-09-17 10:54:37 +080089 Log.d(TAG, "isProfileReady(): "+ mIsProfileReady);
Joseph Pirozzo631768d2016-09-01 14:19:28 -070090 return mIsProfileReady;
91 }
92
ryanywlin44de3a02018-05-02 15:15:37 +080093 @Override
94 public int getProfileId() {
95 return BluetoothProfile.MAP_CLIENT;
96 }
97
timhypengf64f6902018-07-31 15:40:15 +080098 MapClientProfile(Context context, CachedBluetoothDeviceManager deviceManager,
Joseph Pirozzo631768d2016-09-01 14:19:28 -070099 LocalBluetoothProfileManager profileManager) {
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700100 mDeviceManager = deviceManager;
101 mProfileManager = profileManager;
timhypengf64f6902018-07-31 15:40:15 +0800102 BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
103 new MapClientServiceListener(), BluetoothProfile.MAP_CLIENT);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700104 }
105
Leon Liao3b5e6bd2018-09-18 12:45:45 +0800106 public boolean accessProfileEnabled() {
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700107 return true;
108 }
109
110 public boolean isAutoConnectable() {
111 return true;
112 }
113
114 public boolean connect(BluetoothDevice device) {
Chienyuan8862bfb2018-09-17 10:54:37 +0800115 if (mService == null) {
116 return false;
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700117 }
118 return mService.connect(device);
119 }
120
121 public boolean disconnect(BluetoothDevice device) {
Chienyuan8862bfb2018-09-17 10:54:37 +0800122 if (mService == null) {
123 return false;
124 }
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700125 // Downgrade priority as user is disconnecting.
hughchen0f0d83e2019-12-10 14:37:09 +0800126 if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
127 mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700128 }
129 return mService.disconnect(device);
130 }
131
132 public int getConnectionStatus(BluetoothDevice device) {
Chienyuan8862bfb2018-09-17 10:54:37 +0800133 if (mService == null) {
134 return BluetoothProfile.STATE_DISCONNECTED;
135 }
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700136 return mService.getConnectionState(device);
137 }
138
139 public boolean isPreferred(BluetoothDevice device) {
Chienyuan8862bfb2018-09-17 10:54:37 +0800140 if (mService == null) {
141 return false;
142 }
hughchen0f0d83e2019-12-10 14:37:09 +0800143 return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700144 }
145
146 public int getPreferred(BluetoothDevice device) {
Chienyuan8862bfb2018-09-17 10:54:37 +0800147 if (mService == null) {
hughchen0f0d83e2019-12-10 14:37:09 +0800148 return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
Chienyuan8862bfb2018-09-17 10:54:37 +0800149 }
hughchen0f0d83e2019-12-10 14:37:09 +0800150 return mService.getConnectionPolicy(device);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700151 }
152
153 public void setPreferred(BluetoothDevice device, boolean preferred) {
Chienyuan8862bfb2018-09-17 10:54:37 +0800154 if (mService == null) {
155 return;
156 }
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700157 if (preferred) {
hughchen0f0d83e2019-12-10 14:37:09 +0800158 if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
159 mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700160 }
161 } else {
hughchen0f0d83e2019-12-10 14:37:09 +0800162 mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700163 }
164 }
165
166 public List<BluetoothDevice> getConnectedDevices() {
Chienyuan8862bfb2018-09-17 10:54:37 +0800167 if (mService == null) {
168 return new ArrayList<BluetoothDevice>(0);
169 }
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700170 return mService.getDevicesMatchingConnectionStates(
171 new int[] {BluetoothProfile.STATE_CONNECTED,
172 BluetoothProfile.STATE_CONNECTING,
173 BluetoothProfile.STATE_DISCONNECTING});
174 }
175
176 public String toString() {
177 return NAME;
178 }
179
180 public int getOrdinal() {
181 return ORDINAL;
182 }
183
184 public int getNameResource(BluetoothDevice device) {
185 return R.string.bluetooth_profile_map;
186 }
187
188 public int getSummaryResourceForDevice(BluetoothDevice device) {
189 int state = getConnectionStatus(device);
190 switch (state) {
191 case BluetoothProfile.STATE_DISCONNECTED:
192 return R.string.bluetooth_map_profile_summary_use_for;
193
194 case BluetoothProfile.STATE_CONNECTED:
195 return R.string.bluetooth_map_profile_summary_connected;
196
197 default:
Kunhung Lie7b7cb82018-05-17 11:04:54 +0800198 return BluetoothUtils.getConnectionStateSummary(state);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700199 }
200 }
201
202 public int getDrawableResource(BluetoothClass btClass) {
Amin Shaikhf3a94272019-01-29 18:22:14 -0500203 return com.android.internal.R.drawable.ic_phone;
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700204 }
205
206 protected void finalize() {
Chienyuan8862bfb2018-09-17 10:54:37 +0800207 Log.d(TAG, "finalize()");
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700208 if (mService != null) {
209 try {
210 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
Chienyuan8862bfb2018-09-17 10:54:37 +0800211 mService);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700212 mService = null;
213 }catch (Throwable t) {
214 Log.w(TAG, "Error cleaning up MAP Client proxy", t);
215 }
216 }
217 }
218}