• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.settingslib.bluetooth;
18 
19 import android.bluetooth.BluetoothPbapClient;
20 import android.bluetooth.BluetoothAdapter;
21 import android.bluetooth.BluetoothClass;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothProfile;
24 import android.bluetooth.BluetoothUuid;
25 import android.content.Context;
26 import android.os.ParcelUuid;
27 import android.util.Log;
28 
29 import com.android.settingslib.R;
30 
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.List;
34 
35 public final class PbapClientProfile implements LocalBluetoothProfile {
36     private static final String TAG = "PbapClientProfile";
37     private static boolean V = false;
38 
39     private BluetoothPbapClient mService;
40     private boolean mIsProfileReady;
41 
42     private final LocalBluetoothAdapter mLocalAdapter;
43     private final CachedBluetoothDeviceManager mDeviceManager;
44 
45     static final ParcelUuid[] SRC_UUIDS = {
46         BluetoothUuid.PBAP_PSE,
47     };
48 
49     static final String NAME = "PbapClient";
50     private final LocalBluetoothProfileManager mProfileManager;
51 
52     // Order of this profile in device profiles list
53     private static final int ORDINAL = 6;
54 
55     // These callbacks run on the main thread.
56     private final class PbapClientServiceListener
57             implements BluetoothProfile.ServiceListener {
58 
onServiceConnected(int profile, BluetoothProfile proxy)59         public void onServiceConnected(int profile, BluetoothProfile proxy) {
60             if (V) {
61                 Log.d(TAG,"Bluetooth service connected");
62             }
63             mService = (BluetoothPbapClient) proxy;
64             // We just bound to the service, so refresh the UI for any connected PBAP devices.
65             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
66             while (!deviceList.isEmpty()) {
67                 BluetoothDevice nextDevice = deviceList.remove(0);
68                 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
69                 // we may add a new device here, but generally this should not happen
70                 if (device == null) {
71                     Log.w(TAG, "PbapClientProfile found new device: " + nextDevice);
72                     device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
73                 }
74                 device.onProfileStateChanged(PbapClientProfile.this, BluetoothProfile.STATE_CONNECTED);
75                 device.refresh();
76             }
77             mIsProfileReady = true;
78         }
79 
onServiceDisconnected(int profile)80         public void onServiceDisconnected(int profile) {
81             if (V) {
82                 Log.d(TAG,"Bluetooth service disconnected");
83             }
84             mIsProfileReady = false;
85         }
86     }
87 
refreshProfiles()88     private void refreshProfiles() {
89         Collection<CachedBluetoothDevice> cachedDevices = mDeviceManager.getCachedDevicesCopy();
90         for (CachedBluetoothDevice device : cachedDevices) {
91             device.onUuidChanged();
92         }
93     }
94 
pbapClientExists()95     public boolean pbapClientExists() {
96         return (mService != null);
97     }
98 
isProfileReady()99     public boolean isProfileReady() {
100         return mIsProfileReady;
101     }
102 
PbapClientProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager)103     PbapClientProfile(Context context, LocalBluetoothAdapter adapter,
104             CachedBluetoothDeviceManager deviceManager,
105             LocalBluetoothProfileManager profileManager) {
106         mLocalAdapter = adapter;
107         mDeviceManager = deviceManager;
108         mProfileManager = profileManager;
109         mLocalAdapter.getProfileProxy(context, new PbapClientServiceListener(),
110                 BluetoothProfile.PBAP_CLIENT);
111     }
112 
isConnectable()113     public boolean isConnectable() {
114         return true;
115     }
116 
isAutoConnectable()117     public boolean isAutoConnectable() {
118         return true;
119     }
120 
getConnectedDevices()121     public List<BluetoothDevice> getConnectedDevices() {
122         if (mService == null) {
123             return new ArrayList<BluetoothDevice>(0);
124         }
125         return mService.getDevicesMatchingConnectionStates(
126               new int[] {BluetoothProfile.STATE_CONNECTED,
127                          BluetoothProfile.STATE_CONNECTING,
128                          BluetoothProfile.STATE_DISCONNECTING});
129     }
130 
connect(BluetoothDevice device)131     public boolean connect(BluetoothDevice device) {
132         if (V) {
133             Log.d(TAG,"PBAPClientProfile got connect request");
134         }
135         if (mService == null) {
136             return false;
137         }
138         List<BluetoothDevice> srcs = getConnectedDevices();
139         if (srcs != null) {
140             for (BluetoothDevice src : srcs) {
141                 if (src.equals(device)) {
142                     // Connect to same device, Ignore it
143                     Log.d(TAG,"Ignoring Connect");
144                     return true;
145                 }
146             }
147         }
148         Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
149 
150         return mService.connect(device);
151     }
152 
disconnect(BluetoothDevice device)153     public boolean disconnect(BluetoothDevice device) {
154         if (V) {
155             Log.d(TAG,"PBAPClientProfile got disconnect request");
156         }
157         if (mService == null) {
158             return false;
159         }
160         return mService.disconnect(device);
161     }
162 
getConnectionStatus(BluetoothDevice device)163     public int getConnectionStatus(BluetoothDevice device) {
164         if (mService == null) {
165             return BluetoothProfile.STATE_DISCONNECTED;
166         }
167         return mService.getConnectionState(device);
168     }
169 
isPreferred(BluetoothDevice device)170     public boolean isPreferred(BluetoothDevice device) {
171         if (mService == null) {
172             return false;
173         }
174         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
175     }
176 
getPreferred(BluetoothDevice device)177     public int getPreferred(BluetoothDevice device) {
178         if (mService == null) {
179             return BluetoothProfile.PRIORITY_OFF;
180         }
181         return mService.getPriority(device);
182     }
183 
setPreferred(BluetoothDevice device, boolean preferred)184     public void setPreferred(BluetoothDevice device, boolean preferred) {
185         if (mService == null) {
186             return;
187         }
188         if (preferred) {
189             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
190                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
191             }
192         } else {
193             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
194         }
195     }
196 
toString()197     public String toString() {
198         return NAME;
199     }
200 
getOrdinal()201     public int getOrdinal() {
202         return ORDINAL;
203     }
204 
getNameResource(BluetoothDevice device)205     public int getNameResource(BluetoothDevice device) {
206         // we need to have same string in UI as the server side.
207         return R.string.bluetooth_profile_pbap;
208     }
209 
getSummaryResourceForDevice(BluetoothDevice device)210     public int getSummaryResourceForDevice(BluetoothDevice device) {
211         return R.string.bluetooth_profile_pbap_summary;
212     }
213 
getDrawableResource(BluetoothClass btClass)214     public int getDrawableResource(BluetoothClass btClass) {
215         return R.drawable.ic_bt_cellphone;
216     }
217 
finalize()218     protected void finalize() {
219         if (V) {
220             Log.d(TAG, "finalize()");
221         }
222         if (mService != null) {
223             try {
224                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
225                     BluetoothProfile.PBAP_CLIENT,mService);
226                 mService = null;
227             } catch (Throwable t) {
228                 Log.w(TAG, "Error cleaning up PBAP Client proxy", t);
229             }
230         }
231     }
232 }
233