Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2018 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.BluetoothHearingAid;
     23 import android.bluetooth.BluetoothProfile;
     24 import android.content.Context;
     25 import android.util.Log;
     26 
     27 import com.android.settingslib.R;
     28 
     29 import java.util.ArrayList;
     30 import java.util.List;
     31 
     32 public class HearingAidProfile implements LocalBluetoothProfile {
     33     private static final String TAG = "HearingAidProfile";
     34     private static boolean V = true;
     35 
     36     private Context mContext;
     37 
     38     private BluetoothHearingAid mService;
     39     private boolean mIsProfileReady;
     40 
     41     private final CachedBluetoothDeviceManager mDeviceManager;
     42 
     43     static final String NAME = "HearingAid";
     44     private final LocalBluetoothProfileManager mProfileManager;
     45 
     46     // Order of this profile in device profiles list
     47     private static final int ORDINAL = 1;
     48 
     49     // These callbacks run on the main thread.
     50     private final class HearingAidServiceListener
     51             implements BluetoothProfile.ServiceListener {
     52 
     53         public void onServiceConnected(int profile, BluetoothProfile proxy) {
     54             mService = (BluetoothHearingAid) proxy;
     55             // We just bound to the service, so refresh the UI for any connected HearingAid devices.
     56             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
     57             while (!deviceList.isEmpty()) {
     58                 BluetoothDevice nextDevice = deviceList.remove(0);
     59                 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
     60                 // we may add a new device here, but generally this should not happen
     61                 if (device == null) {
     62                     if (V) {
     63                         Log.d(TAG, "HearingAidProfile found new device: " + nextDevice);
     64                     }
     65                     device = mDeviceManager.addDevice(nextDevice);
     66                 }
     67                 device.onProfileStateChanged(HearingAidProfile.this,
     68                         BluetoothProfile.STATE_CONNECTED);
     69                 device.refresh();
     70             }
     71 
     72             // Check current list of CachedDevices to see if any are Hearing Aid devices.
     73             mDeviceManager.updateHearingAidsDevices();
     74             mIsProfileReady=true;
     75             mProfileManager.callServiceConnectedListeners();
     76         }
     77 
     78         public void onServiceDisconnected(int profile) {
     79             mIsProfileReady=false;
     80         }
     81     }
     82 
     83     public boolean isProfileReady() {
     84         return mIsProfileReady;
     85     }
     86 
     87     @Override
     88     public int getProfileId() {
     89         return BluetoothProfile.HEARING_AID;
     90     }
     91 
     92     HearingAidProfile(Context context, CachedBluetoothDeviceManager deviceManager,
     93             LocalBluetoothProfileManager profileManager) {
     94         mContext = context;
     95         mDeviceManager = deviceManager;
     96         mProfileManager = profileManager;
     97         BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
     98                 new HearingAidServiceListener(), BluetoothProfile.HEARING_AID);
     99     }
    100 
    101     public boolean accessProfileEnabled() {
    102         return false;
    103     }
    104 
    105     public boolean isAutoConnectable() {
    106         return true;
    107     }
    108 
    109     /**
    110      * Get Hearing Aid devices matching connection states{
    111      * @code BluetoothProfile.STATE_CONNECTED,
    112      * @code BluetoothProfile.STATE_CONNECTING,
    113      * @code BluetoothProfile.STATE_DISCONNECTING}
    114      *
    115      * @return Matching device list
    116      */
    117     public List<BluetoothDevice> getConnectedDevices() {
    118         return getDevicesByStates(new int[] {
    119                 BluetoothProfile.STATE_CONNECTED,
    120                 BluetoothProfile.STATE_CONNECTING,
    121                 BluetoothProfile.STATE_DISCONNECTING});
    122     }
    123 
    124     /**
    125      * Get Hearing Aid devices matching connection states{
    126      * @code BluetoothProfile.STATE_DISCONNECTED,
    127      * @code BluetoothProfile.STATE_CONNECTED,
    128      * @code BluetoothProfile.STATE_CONNECTING,
    129      * @code BluetoothProfile.STATE_DISCONNECTING}
    130      *
    131      * @return Matching device list
    132      */
    133     public List<BluetoothDevice> getConnectableDevices() {
    134         return getDevicesByStates(new int[] {
    135                 BluetoothProfile.STATE_DISCONNECTED,
    136                 BluetoothProfile.STATE_CONNECTED,
    137                 BluetoothProfile.STATE_CONNECTING,
    138                 BluetoothProfile.STATE_DISCONNECTING});
    139     }
    140 
    141     private List<BluetoothDevice> getDevicesByStates(int[] states) {
    142         if (mService == null) {
    143             return new ArrayList<BluetoothDevice>(0);
    144         }
    145         return mService.getDevicesMatchingConnectionStates(states);
    146     }
    147 
    148     public boolean connect(BluetoothDevice device) {
    149         if (mService == null) return false;
    150         return mService.connect(device);
    151     }
    152 
    153     public boolean disconnect(BluetoothDevice device) {
    154         if (mService == null) return false;
    155         // Downgrade priority as user is disconnecting the hearing aid.
    156         if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
    157             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    158         }
    159         return mService.disconnect(device);
    160     }
    161 
    162     public int getConnectionStatus(BluetoothDevice device) {
    163         if (mService == null) {
    164             return BluetoothProfile.STATE_DISCONNECTED;
    165         }
    166         return mService.getConnectionState(device);
    167     }
    168 
    169     public boolean setActiveDevice(BluetoothDevice device) {
    170         if (mService == null) return false;
    171         return mService.setActiveDevice(device);
    172     }
    173 
    174     public List<BluetoothDevice> getActiveDevices() {
    175         if (mService == null) return new ArrayList<>();
    176         return mService.getActiveDevices();
    177     }
    178 
    179     public boolean isPreferred(BluetoothDevice device) {
    180         if (mService == null) return false;
    181         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
    182     }
    183 
    184     public int getPreferred(BluetoothDevice device) {
    185         if (mService == null) return BluetoothProfile.PRIORITY_OFF;
    186         return mService.getPriority(device);
    187     }
    188 
    189     public void setPreferred(BluetoothDevice device, boolean preferred) {
    190         if (mService == null) return;
    191         if (preferred) {
    192             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
    193                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    194             }
    195         } else {
    196             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
    197         }
    198     }
    199 
    200     public int getVolume() {
    201         if (mService == null) {
    202             return 0;
    203         }
    204         return mService.getVolume();
    205     }
    206 
    207     public void setVolume(int volume) {
    208         if (mService == null) {
    209             return;
    210         }
    211         mService.setVolume(volume);
    212     }
    213 
    214     public long getHiSyncId(BluetoothDevice device) {
    215         if (mService == null) {
    216             return BluetoothHearingAid.HI_SYNC_ID_INVALID;
    217         }
    218         return mService.getHiSyncId(device);
    219     }
    220 
    221     public int getDeviceSide(BluetoothDevice device) {
    222         if (mService == null) {
    223             return BluetoothHearingAid.SIDE_LEFT;
    224         }
    225         return mService.getDeviceSide(device);
    226     }
    227 
    228     public int getDeviceMode(BluetoothDevice device) {
    229         if (mService == null) {
    230             return BluetoothHearingAid.MODE_MONAURAL;
    231         }
    232         return mService.getDeviceMode(device);
    233     }
    234 
    235     public String toString() {
    236         return NAME;
    237     }
    238 
    239     public int getOrdinal() {
    240         return ORDINAL;
    241     }
    242 
    243     public int getNameResource(BluetoothDevice device) {
    244         return R.string.bluetooth_profile_hearing_aid;
    245     }
    246 
    247     public int getSummaryResourceForDevice(BluetoothDevice device) {
    248         int state = getConnectionStatus(device);
    249         switch (state) {
    250             case BluetoothProfile.STATE_DISCONNECTED:
    251                 return R.string.bluetooth_hearing_aid_profile_summary_use_for;
    252 
    253             case BluetoothProfile.STATE_CONNECTED:
    254                 return R.string.bluetooth_hearing_aid_profile_summary_connected;
    255 
    256             default:
    257                 return BluetoothUtils.getConnectionStateSummary(state);
    258         }
    259     }
    260 
    261     public int getDrawableResource(BluetoothClass btClass) {
    262         return com.android.internal.R.drawable.ic_bt_hearing_aid;
    263     }
    264 
    265     protected void finalize() {
    266         Log.d(TAG, "finalize()");
    267         if (mService != null) {
    268             try {
    269                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEARING_AID,
    270                                                                        mService);
    271                 mService = null;
    272             }catch (Throwable t) {
    273                 Log.w(TAG, "Error cleaning up Hearing Aid proxy", t);
    274             }
    275         }
    276     }
    277 }
    278