Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2015 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.BluetoothAdapter;
     20 import android.bluetooth.BluetoothClass;
     21 import android.bluetooth.BluetoothDevice;
     22 import android.bluetooth.BluetoothSap;
     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.List;
     33 
     34 /**
     35  * SapProfile handles Bluetooth SAP profile.
     36  */
     37 final class SapProfile implements LocalBluetoothProfile {
     38     private static final String TAG = "SapProfile";
     39     private static boolean V = true;
     40 
     41     private BluetoothSap 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.SAP,
     50     };
     51 
     52     static final String NAME = "SAP";
     53 
     54     // Order of this profile in device profiles list
     55     private static final int ORDINAL = 10;
     56 
     57     // These callbacks run on the main thread.
     58     private final class SapServiceListener
     59             implements BluetoothProfile.ServiceListener {
     60 
     61         public void onServiceConnected(int profile, BluetoothProfile proxy) {
     62             if (V) Log.d(TAG,"Bluetooth service connected");
     63             mService = (BluetoothSap) proxy;
     64             // We just bound to the service, so refresh the UI for any connected SAP 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, "SapProfile found new device: " + nextDevice);
     72                     device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
     73                 }
     74                 device.onProfileStateChanged(SapProfile.this,
     75                         BluetoothProfile.STATE_CONNECTED);
     76                 device.refresh();
     77             }
     78 
     79             mProfileManager.callServiceConnectedListeners();
     80             mIsProfileReady=true;
     81         }
     82 
     83         public void onServiceDisconnected(int profile) {
     84             if (V) Log.d(TAG,"Bluetooth service disconnected");
     85             mProfileManager.callServiceDisconnectedListeners();
     86             mIsProfileReady=false;
     87         }
     88     }
     89 
     90     public boolean isProfileReady() {
     91         return mIsProfileReady;
     92     }
     93 
     94     SapProfile(Context context, LocalBluetoothAdapter adapter,
     95             CachedBluetoothDeviceManager deviceManager,
     96             LocalBluetoothProfileManager profileManager) {
     97         mLocalAdapter = adapter;
     98         mDeviceManager = deviceManager;
     99         mProfileManager = profileManager;
    100         mLocalAdapter.getProfileProxy(context, new SapServiceListener(),
    101                 BluetoothProfile.SAP);
    102     }
    103 
    104     public boolean isConnectable() {
    105         return true;
    106     }
    107 
    108     public boolean isAutoConnectable() {
    109         return true;
    110     }
    111 
    112     public boolean connect(BluetoothDevice device) {
    113         if (mService == null) return false;
    114         List<BluetoothDevice> sinks = mService.getConnectedDevices();
    115         if (sinks != null) {
    116             for (BluetoothDevice sink : sinks) {
    117                 mService.disconnect(sink);
    118             }
    119         }
    120         return mService.connect(device);
    121     }
    122 
    123     public boolean disconnect(BluetoothDevice device) {
    124         if (mService == null) return false;
    125         List<BluetoothDevice> deviceList = mService.getConnectedDevices();
    126         if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
    127             if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
    128                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    129             }
    130             return mService.disconnect(device);
    131         } else {
    132             return false;
    133         }
    134     }
    135 
    136     public int getConnectionStatus(BluetoothDevice device) {
    137         if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
    138         List<BluetoothDevice> deviceList = mService.getConnectedDevices();
    139 
    140         return !deviceList.isEmpty() && deviceList.get(0).equals(device)
    141                 ? mService.getConnectionState(device)
    142                 : BluetoothProfile.STATE_DISCONNECTED;
    143     }
    144 
    145     public boolean isPreferred(BluetoothDevice device) {
    146         if (mService == null) return false;
    147         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
    148     }
    149 
    150     public int getPreferred(BluetoothDevice device) {
    151         if (mService == null) return BluetoothProfile.PRIORITY_OFF;
    152         return mService.getPriority(device);
    153     }
    154 
    155     public void setPreferred(BluetoothDevice device, boolean preferred) {
    156         if (mService == null) return;
    157         if (preferred) {
    158             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
    159                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    160             }
    161         } else {
    162             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
    163         }
    164     }
    165 
    166     public List<BluetoothDevice> getConnectedDevices() {
    167         if (mService == null) return new ArrayList<BluetoothDevice>(0);
    168         return mService.getDevicesMatchingConnectionStates(
    169               new int[] {BluetoothProfile.STATE_CONNECTED,
    170                          BluetoothProfile.STATE_CONNECTING,
    171                          BluetoothProfile.STATE_DISCONNECTING});
    172     }
    173 
    174     public String toString() {
    175         return NAME;
    176     }
    177 
    178     public int getOrdinal() {
    179         return ORDINAL;
    180     }
    181 
    182     public int getNameResource(BluetoothDevice device) {
    183         return R.string.bluetooth_profile_sap;
    184     }
    185 
    186     public int getSummaryResourceForDevice(BluetoothDevice device) {
    187         int state = getConnectionStatus(device);
    188         switch (state) {
    189             case BluetoothProfile.STATE_DISCONNECTED:
    190                 return R.string.bluetooth_sap_profile_summary_use_for;
    191 
    192             case BluetoothProfile.STATE_CONNECTED:
    193                 return R.string.bluetooth_sap_profile_summary_connected;
    194 
    195             default:
    196                 return Utils.getConnectionStateSummary(state);
    197         }
    198     }
    199 
    200     public int getDrawableResource(BluetoothClass btClass) {
    201         return R.drawable.ic_bt_cellphone;
    202     }
    203 
    204     protected void finalize() {
    205         if (V) Log.d(TAG, "finalize()");
    206         if (mService != null) {
    207             try {
    208                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.SAP,
    209                                                                        mService);
    210                 mService = null;
    211             }catch (Throwable t) {
    212                 Log.w(TAG, "Error cleaning up SAP proxy", t);
    213             }
    214         }
    215     }
    216 }
    217