• 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 
103     @Override
getProfileId()104     public int getProfileId() {
105         return BluetoothProfile.PBAP_CLIENT;
106     }
107 
PbapClientProfile(Context context, LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager)108     PbapClientProfile(Context context, LocalBluetoothAdapter adapter,
109             CachedBluetoothDeviceManager deviceManager,
110             LocalBluetoothProfileManager profileManager) {
111         mLocalAdapter = adapter;
112         mDeviceManager = deviceManager;
113         mProfileManager = profileManager;
114         mLocalAdapter.getProfileProxy(context, new PbapClientServiceListener(),
115                 BluetoothProfile.PBAP_CLIENT);
116     }
117 
isConnectable()118     public boolean isConnectable() {
119         return true;
120     }
121 
isAutoConnectable()122     public boolean isAutoConnectable() {
123         return true;
124     }
125 
getConnectedDevices()126     public List<BluetoothDevice> getConnectedDevices() {
127         if (mService == null) {
128             return new ArrayList<BluetoothDevice>(0);
129         }
130         return mService.getDevicesMatchingConnectionStates(
131               new int[] {BluetoothProfile.STATE_CONNECTED,
132                          BluetoothProfile.STATE_CONNECTING,
133                          BluetoothProfile.STATE_DISCONNECTING});
134     }
135 
connect(BluetoothDevice device)136     public boolean connect(BluetoothDevice device) {
137         if (V) {
138             Log.d(TAG,"PBAPClientProfile got connect request");
139         }
140         if (mService == null) {
141             return false;
142         }
143         List<BluetoothDevice> srcs = getConnectedDevices();
144         if (srcs != null) {
145             for (BluetoothDevice src : srcs) {
146                 if (src.equals(device)) {
147                     // Connect to same device, Ignore it
148                     Log.d(TAG,"Ignoring Connect");
149                     return true;
150                 }
151             }
152         }
153         Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
154 
155         return mService.connect(device);
156     }
157 
disconnect(BluetoothDevice device)158     public boolean disconnect(BluetoothDevice device) {
159         if (V) {
160             Log.d(TAG,"PBAPClientProfile got disconnect request");
161         }
162         if (mService == null) {
163             return false;
164         }
165         return mService.disconnect(device);
166     }
167 
getConnectionStatus(BluetoothDevice device)168     public int getConnectionStatus(BluetoothDevice device) {
169         if (mService == null) {
170             return BluetoothProfile.STATE_DISCONNECTED;
171         }
172         return mService.getConnectionState(device);
173     }
174 
isPreferred(BluetoothDevice device)175     public boolean isPreferred(BluetoothDevice device) {
176         if (mService == null) {
177             return false;
178         }
179         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
180     }
181 
getPreferred(BluetoothDevice device)182     public int getPreferred(BluetoothDevice device) {
183         if (mService == null) {
184             return BluetoothProfile.PRIORITY_OFF;
185         }
186         return mService.getPriority(device);
187     }
188 
setPreferred(BluetoothDevice device, boolean preferred)189     public void setPreferred(BluetoothDevice device, boolean preferred) {
190         if (mService == null) {
191             return;
192         }
193         if (preferred) {
194             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
195                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
196             }
197         } else {
198             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
199         }
200     }
201 
toString()202     public String toString() {
203         return NAME;
204     }
205 
getOrdinal()206     public int getOrdinal() {
207         return ORDINAL;
208     }
209 
getNameResource(BluetoothDevice device)210     public int getNameResource(BluetoothDevice device) {
211         // we need to have same string in UI as the server side.
212         return R.string.bluetooth_profile_pbap;
213     }
214 
getSummaryResourceForDevice(BluetoothDevice device)215     public int getSummaryResourceForDevice(BluetoothDevice device) {
216         return R.string.bluetooth_profile_pbap_summary;
217     }
218 
getDrawableResource(BluetoothClass btClass)219     public int getDrawableResource(BluetoothClass btClass) {
220         return R.drawable.ic_bt_cellphone;
221     }
222 
finalize()223     protected void finalize() {
224         if (V) {
225             Log.d(TAG, "finalize()");
226         }
227         if (mService != null) {
228             try {
229                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
230                     BluetoothProfile.PBAP_CLIENT,mService);
231                 mService = null;
232             } catch (Throwable t) {
233                 Log.w(TAG, "Error cleaning up PBAP Client proxy", t);
234             }
235         }
236     }
237 }
238