Home | History | Annotate | Download | only in bluetooth
      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 
     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.BluetoothMapClient;
     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  * MapClientProfile handles Bluetooth MAP profile.
     36  */
     37 public 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 && connectedDevices.contains(device)) {
    119             // Connect to same device, Ignore it
    120             Log.d(TAG,"Ignoring Connect");
    121             return true;
    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