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.bluetooth.btservice;
18 
19 import java.util.ArrayList;
20 
21 import android.bluetooth.BluetoothProfile;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.res.Resources;
25 import android.provider.Settings;
26 import android.util.Log;
27 
28 import com.android.bluetooth.R;
29 import com.android.bluetooth.a2dp.A2dpService;
30 import com.android.bluetooth.a2dpsink.A2dpSinkService;
31 import com.android.bluetooth.avrcpcontroller.AvrcpControllerService;
32 import com.android.bluetooth.hdp.HealthService;
33 import com.android.bluetooth.hfp.HeadsetService;
34 import com.android.bluetooth.hfpclient.HeadsetClientService;
35 import com.android.bluetooth.hid.HidService;
36 import com.android.bluetooth.pan.PanService;
37 import com.android.bluetooth.gatt.GattService;
38 import com.android.bluetooth.map.BluetoothMapService;
39 import com.android.bluetooth.mapclient.MapClientService;
40 import com.android.bluetooth.sap.SapService;
41 import com.android.bluetooth.pbapclient.PbapClientService;
42 import com.android.bluetooth.hid.HidDevService;
43 import com.android.bluetooth.pbap.BluetoothPbapService;
44 import com.android.bluetooth.opp.BluetoothOppService;
45 
46 public class Config {
47     private static final String TAG = "AdapterServiceConfig";
48     /**
49      * List of profile services.
50      */
51     @SuppressWarnings("rawtypes")
52     // Do not inclue OPP and PBAP, because their services
53     // are not managed by AdapterService
54     private static final Class[] PROFILE_SERVICES = {HeadsetService.class, A2dpService.class,
55             A2dpSinkService.class, HidService.class, HealthService.class, PanService.class,
56             GattService.class, BluetoothMapService.class, HeadsetClientService.class,
57             AvrcpControllerService.class, SapService.class, PbapClientService.class,
58             MapClientService.class, HidDevService.class, BluetoothOppService.class,
59             BluetoothPbapService.class};
60     /**
61      * Resource flag to indicate whether profile is supported or not.
62      */
63     private static final int[] PROFILE_SERVICES_FLAG = {R.bool.profile_supported_hs_hfp,
64             R.bool.profile_supported_a2dp, R.bool.profile_supported_a2dp_sink,
65             R.bool.profile_supported_hid, R.bool.profile_supported_hdp,
66             R.bool.profile_supported_pan, R.bool.profile_supported_gatt,
67             R.bool.profile_supported_map, R.bool.profile_supported_hfpclient,
68             R.bool.profile_supported_avrcp_controller, R.bool.profile_supported_sap,
69             R.bool.profile_supported_pbapclient, R.bool.profile_supported_mapmce,
70             R.bool.profile_supported_hidd, R.bool.profile_supported_opp,
71             R.bool.profile_supported_pbap};
72 
73     private static Class[] SUPPORTED_PROFILES = new Class[0];
74 
init(Context ctx)75     static void init(Context ctx) {
76         if (ctx == null) {
77             return;
78         }
79         Resources resources = ctx.getResources();
80         if (resources == null) {
81             return;
82         }
83 
84         ArrayList<Class> profiles = new ArrayList<Class>(PROFILE_SERVICES.length);
85         for (int i=0; i < PROFILE_SERVICES_FLAG.length; i++) {
86             boolean supported = resources.getBoolean(PROFILE_SERVICES_FLAG[i]);
87             if (supported && !isProfileDisabled(ctx, PROFILE_SERVICES[i])) {
88                 Log.d(TAG, "Adding " + PROFILE_SERVICES[i].getSimpleName());
89                 profiles.add(PROFILE_SERVICES[i]);
90             }
91         }
92         SUPPORTED_PROFILES = profiles.toArray(new Class[profiles.size()]);
93     }
94 
getSupportedProfiles()95     static Class[]  getSupportedProfiles() {
96         return SUPPORTED_PROFILES;
97     }
98 
getSupportedProfilesBitMask()99     static long getSupportedProfilesBitMask() {
100         long mask = 0;
101         for (final Class profileClass : getSupportedProfiles()) {
102             final int profileIndex = getProfileIndex(profileClass);
103 
104             if (profileIndex != -1) {
105                 mask |= 1 << getProfileIndex(profileClass);
106             }
107         }
108 
109         return mask;
110     }
111 
isProfileDisabled(Context context, Class profile)112     private static boolean isProfileDisabled(Context context, Class profile) {
113         final int profileIndex = getProfileIndex(profile);
114 
115         if (profileIndex == -1) {
116             Log.w(TAG, "Could not find profile bit mask");
117             return false;
118         }
119 
120         final ContentResolver resolver = context.getContentResolver();
121         final long disabledProfilesBitMask = Settings.Global.getLong(resolver,
122                 Settings.Global.BLUETOOTH_DISABLED_PROFILES, 0);
123         final long profileBit = 1 << profileIndex;
124 
125         return (disabledProfilesBitMask & profileBit) != 0;
126     }
127 
getProfileIndex(Class profile)128     private static int getProfileIndex(Class profile) {
129         int profileIndex = -1;
130 
131         if (profile == HeadsetService.class) {
132             profileIndex = BluetoothProfile.HEADSET;
133         } else if (profile == A2dpService.class) {
134             profileIndex = BluetoothProfile.A2DP;
135         } else if (profile == A2dpSinkService.class) {
136             profileIndex = BluetoothProfile.A2DP_SINK;
137         } else if (profile == HidService.class) {
138             profileIndex = BluetoothProfile.INPUT_DEVICE;
139         } else if (profile == HealthService.class) {
140             profileIndex = BluetoothProfile.HEALTH;
141         } else if (profile == PanService.class) {
142             profileIndex = BluetoothProfile.PAN;
143         } else if (profile == GattService.class) {
144             profileIndex = BluetoothProfile.GATT;
145         } else if (profile == BluetoothMapService.class) {
146             profileIndex = BluetoothProfile.MAP;
147         } else if (profile == HeadsetClientService.class) {
148             profileIndex = BluetoothProfile.HEADSET_CLIENT;
149         } else if (profile == AvrcpControllerService.class) {
150             profileIndex = BluetoothProfile.AVRCP_CONTROLLER;
151         } else if (profile == SapService.class) {
152             profileIndex = BluetoothProfile.SAP;
153         } else if (profile == PbapClientService.class) {
154             profileIndex = BluetoothProfile.PBAP_CLIENT;
155         } else if (profile == MapClientService.class) {
156             profileIndex = BluetoothProfile.MAP_CLIENT;
157         } else if (profile == HidDevService.class) {
158             profileIndex = BluetoothProfile.INPUT_HOST;
159         }
160 
161         return profileIndex;
162     }
163 }
164