• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.tv.settings.accessories;
18 
19 import android.bluetooth.BluetoothAdapter;
20 import android.bluetooth.BluetoothClass;
21 import android.bluetooth.BluetoothDevice;
22 import android.bluetooth.BluetoothProfile;
23 import android.content.Context;
24 import android.util.Log;
25 
26 import androidx.annotation.DrawableRes;
27 import androidx.annotation.NonNull;
28 
29 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
30 import com.android.settingslib.bluetooth.LocalBluetoothManager;
31 import com.android.tv.settings.R;
32 
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.FutureTask;
38 
39 /** Provide utilities for Remote & Accessories. */
40 final class AccessoryUtils {
41 
42     public static final String TAG = "AccessoryUtils";
43 
44     private static final int MINOR_MASK = 0b11111100;
45     // Includes any generic keyboards or pointers, and any joystick, game pad, or remote subtypes.
46     private static final int MINOR_REMOTE_MASK = 0b11001100;
47     private static List<String> sKnownDeviceLabels = null;
48 
49     /** This allows OEM to easily override the main Service if desired. */
getBluetoothDeviceServiceClass()50     public static Class getBluetoothDeviceServiceClass() {
51         return BluetoothDevicesService.class;
52     }
53 
getLocalBluetoothManager(Context context)54     public static LocalBluetoothManager getLocalBluetoothManager(Context context) {
55         final FutureTask<LocalBluetoothManager> localBluetoothManagerFutureTask =
56                 new FutureTask<>(
57                         // Avoid StrictMode ThreadPolicy violation
58                         () -> LocalBluetoothManager.getInstance(
59                                 context, (c, bluetoothManager) -> {
60                                 })
61                 );
62         try {
63             localBluetoothManagerFutureTask.run();
64             return localBluetoothManagerFutureTask.get();
65         } catch (InterruptedException | ExecutionException e) {
66             Log.w(TAG, "Error getting LocalBluetoothManager.", e);
67             return null;
68         }
69     }
70 
getCachedBluetoothDevice( Context context, BluetoothDevice device)71     public static CachedBluetoothDevice getCachedBluetoothDevice(
72             Context context, BluetoothDevice device) {
73         LocalBluetoothManager localBluetoothManager = getLocalBluetoothManager(context);
74         if (localBluetoothManager != null) {
75             return localBluetoothManager.getCachedDeviceManager().findDevice(device);
76         }
77         return null;
78     }
79 
getDefaultBluetoothAdapter()80     public static BluetoothAdapter getDefaultBluetoothAdapter() {
81         final FutureTask<BluetoothAdapter> defaultBluetoothAdapterFutureTask =
82                 new FutureTask<>(
83                         // Avoid StrictMode ThreadPolicy violation
84                         BluetoothAdapter::getDefaultAdapter);
85         try {
86             defaultBluetoothAdapterFutureTask.run();
87             return defaultBluetoothAdapterFutureTask.get();
88         } catch (InterruptedException | ExecutionException e) {
89             Log.w(TAG, "Error getting default BluetoothAdapter.", e);
90             return null;
91         }
92     }
93 
getLocalName(BluetoothDevice device)94     public static String getLocalName(BluetoothDevice device) {
95         if (device == null) {
96             return null;
97         }
98         return device.getAlias();
99     }
100 
isBluetoothEnabled()101     public static boolean isBluetoothEnabled() {
102         return getDefaultBluetoothAdapter() != null && getDefaultBluetoothAdapter().isEnabled();
103     }
104 
isConnected(BluetoothDevice device)105     public static boolean isConnected(BluetoothDevice device) {
106         if (device == null) {
107             return false;
108         }
109         return device.getBondState() == BluetoothDevice.BOND_BONDED && device.isConnected();
110     }
111 
isBonded(BluetoothDevice device)112     public static boolean isBonded(BluetoothDevice device) {
113         if (device == null) {
114             return false;
115         }
116         return device.getBondState() == BluetoothDevice.BOND_BONDED && !device.isConnected();
117     }
118 
isRemoteClass(BluetoothDevice device)119     public static boolean isRemoteClass(BluetoothDevice device) {
120         if (device == null || device.getBluetoothClass() == null) {
121             return false;
122         }
123         int major = device.getBluetoothClass().getMajorDeviceClass();
124         int minor = device.getBluetoothClass().getDeviceClass() & MINOR_MASK;
125         return BluetoothClass.Device.Major.PERIPHERAL == major
126                 && (minor & ~MINOR_REMOTE_MASK) == 0;
127     }
128 
129     // For partner, this will be used to identify official device to omit it in the generic
130     // accessories section since the device's settings will be displayed in partner-implemented
131     // Slice.
isKnownDevice(Context context, BluetoothDevice device)132     public static boolean isKnownDevice(Context context, BluetoothDevice device) {
133         if (device == null || device.getName() == null) {
134             return false;
135         }
136         if (sKnownDeviceLabels == null) {
137             if (context == null) {
138                 return false;
139             } else {
140                 sKnownDeviceLabels =
141                         Collections.unmodifiableList(
142                                 Arrays.asList(context.getResources().getStringArray(
143                                         R.array.known_bluetooth_device_labels)));
144             }
145         }
146 
147         final String name = device.getName().toLowerCase();
148         for (String knownLabel : sKnownDeviceLabels) {
149             if (name.contains(knownLabel.toLowerCase())) {
150                 return true;
151             }
152         }
153         return false;
154     }
155 
AccessoryUtils()156     private AccessoryUtils() {
157         // do not allow instantiation
158     }
159 }