1 /*
2  * Copyright 2019 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.storage;
18 
19 import android.bluetooth.BluetoothA2dp;
20 import android.bluetooth.BluetoothA2dp.OptionalCodecsPreferenceStatus;
21 import android.bluetooth.BluetoothA2dp.OptionalCodecsSupportStatus;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothProfile;
24 
25 import androidx.annotation.NonNull;
26 import androidx.room.Embedded;
27 import androidx.room.Entity;
28 import androidx.room.PrimaryKey;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 @Entity(tableName = "metadata")
34 class Metadata {
35     @PrimaryKey
36     @NonNull
37     private String address;
38 
39     public boolean migrated;
40 
41     @Embedded
42     public ProfilePrioritiesEntity profileConnectionPolicies;
43 
44     @Embedded
45     @NonNull
46     public CustomizedMetadataEntity publicMetadata;
47 
48     public @OptionalCodecsSupportStatus int a2dpSupportsOptionalCodecs;
49     public @OptionalCodecsPreferenceStatus int a2dpOptionalCodecsEnabled;
50 
51     public long last_active_time;
52     public boolean is_active_a2dp_device;
53 
Metadata(String address)54     Metadata(String address) {
55         this.address = address;
56         migrated = false;
57         profileConnectionPolicies = new ProfilePrioritiesEntity();
58         publicMetadata = new CustomizedMetadataEntity();
59         a2dpSupportsOptionalCodecs = BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN;
60         a2dpOptionalCodecsEnabled = BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN;
61         last_active_time = MetadataDatabase.sCurrentConnectionNumber++;
62         is_active_a2dp_device = true;
63     }
64 
getAddress()65     String getAddress() {
66         return address;
67     }
68 
setProfileConnectionPolicy(int profile, int connectionPolicy)69     void setProfileConnectionPolicy(int profile, int connectionPolicy) {
70         // We no longer support BluetoothProfile.PRIORITY_AUTO_CONNECT and are merging it into
71         // BluetoothProfile.CONNECTION_POLICY_ALLOWED
72         if (connectionPolicy > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
73             connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED;
74         }
75 
76         switch (profile) {
77             case BluetoothProfile.A2DP:
78                 profileConnectionPolicies.a2dp_connection_policy = connectionPolicy;
79                 break;
80             case BluetoothProfile.A2DP_SINK:
81                 profileConnectionPolicies.a2dp_sink_connection_policy = connectionPolicy;
82                 break;
83             case BluetoothProfile.HEADSET:
84                 profileConnectionPolicies.hfp_connection_policy = connectionPolicy;
85                 break;
86             case BluetoothProfile.HEADSET_CLIENT:
87                 profileConnectionPolicies.hfp_client_connection_policy = connectionPolicy;
88                 break;
89             case BluetoothProfile.HID_HOST:
90                 profileConnectionPolicies.hid_host_connection_policy = connectionPolicy;
91                 break;
92             case BluetoothProfile.PAN:
93                 profileConnectionPolicies.pan_connection_policy = connectionPolicy;
94                 break;
95             case BluetoothProfile.PBAP:
96                 profileConnectionPolicies.pbap_connection_policy = connectionPolicy;
97                 break;
98             case BluetoothProfile.PBAP_CLIENT:
99                 profileConnectionPolicies.pbap_client_connection_policy = connectionPolicy;
100                 break;
101             case BluetoothProfile.MAP:
102                 profileConnectionPolicies.map_connection_policy = connectionPolicy;
103                 break;
104             case BluetoothProfile.MAP_CLIENT:
105                 profileConnectionPolicies.map_client_connection_policy = connectionPolicy;
106                 break;
107             case BluetoothProfile.SAP:
108                 profileConnectionPolicies.sap_connection_policy = connectionPolicy;
109                 break;
110             case BluetoothProfile.HEARING_AID:
111                 profileConnectionPolicies.hearing_aid_connection_policy = connectionPolicy;
112                 break;
113             case BluetoothProfile.LE_AUDIO:
114                 profileConnectionPolicies.le_audio_connection_policy = connectionPolicy;
115                 break;
116             default:
117                 throw new IllegalArgumentException("invalid profile " + profile);
118         }
119     }
120 
getProfileConnectionPolicy(int profile)121     int getProfileConnectionPolicy(int profile) {
122         switch (profile) {
123             case BluetoothProfile.A2DP:
124                 return profileConnectionPolicies.a2dp_connection_policy;
125             case BluetoothProfile.A2DP_SINK:
126                 return profileConnectionPolicies.a2dp_sink_connection_policy;
127             case BluetoothProfile.HEADSET:
128                 return profileConnectionPolicies.hfp_connection_policy;
129             case BluetoothProfile.HEADSET_CLIENT:
130                 return profileConnectionPolicies.hfp_client_connection_policy;
131             case BluetoothProfile.HID_HOST:
132                 return profileConnectionPolicies.hid_host_connection_policy;
133             case BluetoothProfile.PAN:
134                 return profileConnectionPolicies.pan_connection_policy;
135             case BluetoothProfile.PBAP:
136                 return profileConnectionPolicies.pbap_connection_policy;
137             case BluetoothProfile.PBAP_CLIENT:
138                 return profileConnectionPolicies.pbap_client_connection_policy;
139             case BluetoothProfile.MAP:
140                 return profileConnectionPolicies.map_connection_policy;
141             case BluetoothProfile.MAP_CLIENT:
142                 return profileConnectionPolicies.map_client_connection_policy;
143             case BluetoothProfile.SAP:
144                 return profileConnectionPolicies.sap_connection_policy;
145             case BluetoothProfile.HEARING_AID:
146                 return profileConnectionPolicies.hearing_aid_connection_policy;
147             case BluetoothProfile.LE_AUDIO:
148                 return profileConnectionPolicies.le_audio_connection_policy;
149         }
150         return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
151     }
152 
setCustomizedMeta(int key, byte[] value)153     void setCustomizedMeta(int key, byte[] value) {
154         switch (key) {
155             case BluetoothDevice.METADATA_MANUFACTURER_NAME:
156                 publicMetadata.manufacturer_name = value;
157                 break;
158             case BluetoothDevice.METADATA_MODEL_NAME:
159                 publicMetadata.model_name = value;
160                 break;
161             case BluetoothDevice.METADATA_SOFTWARE_VERSION:
162                 publicMetadata.software_version = value;
163                 break;
164             case BluetoothDevice.METADATA_HARDWARE_VERSION:
165                 publicMetadata.hardware_version = value;
166                 break;
167             case BluetoothDevice.METADATA_COMPANION_APP:
168                 publicMetadata.companion_app = value;
169                 break;
170             case BluetoothDevice.METADATA_MAIN_ICON:
171                 publicMetadata.main_icon = value;
172                 break;
173             case BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET:
174                 publicMetadata.is_untethered_headset = value;
175                 break;
176             case BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON:
177                 publicMetadata.untethered_left_icon = value;
178                 break;
179             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON:
180                 publicMetadata.untethered_right_icon = value;
181                 break;
182             case BluetoothDevice.METADATA_UNTETHERED_CASE_ICON:
183                 publicMetadata.untethered_case_icon = value;
184                 break;
185             case BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY:
186                 publicMetadata.untethered_left_battery = value;
187                 break;
188             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY:
189                 publicMetadata.untethered_right_battery = value;
190                 break;
191             case BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY:
192                 publicMetadata.untethered_case_battery = value;
193                 break;
194             case BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING:
195                 publicMetadata.untethered_left_charging = value;
196                 break;
197             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING:
198                 publicMetadata.untethered_right_charging = value;
199                 break;
200             case BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING:
201                 publicMetadata.untethered_case_charging = value;
202                 break;
203             case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
204                 publicMetadata.enhanced_settings_ui_uri = value;
205                 break;
206             case BluetoothDevice.METADATA_DEVICE_TYPE:
207                 publicMetadata.device_type = value;
208                 break;
209             case BluetoothDevice.METADATA_MAIN_BATTERY:
210                 publicMetadata.main_battery = value;
211                 break;
212             case BluetoothDevice.METADATA_MAIN_CHARGING:
213                 publicMetadata.main_charging = value;
214                 break;
215             case BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD:
216                 publicMetadata.main_low_battery_threshold = value;
217                 break;
218             case BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD:
219                 publicMetadata.untethered_left_low_battery_threshold = value;
220                 break;
221             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD:
222                 publicMetadata.untethered_right_low_battery_threshold = value;
223                 break;
224             case BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD:
225                 publicMetadata.untethered_case_low_battery_threshold = value;
226                 break;
227         }
228     }
229 
getCustomizedMeta(int key)230     byte[] getCustomizedMeta(int key) {
231         byte[] value = null;
232         switch (key) {
233             case BluetoothDevice.METADATA_MANUFACTURER_NAME:
234                 value = publicMetadata.manufacturer_name;
235                 break;
236             case BluetoothDevice.METADATA_MODEL_NAME:
237                 value = publicMetadata.model_name;
238                 break;
239             case BluetoothDevice.METADATA_SOFTWARE_VERSION:
240                 value = publicMetadata.software_version;
241                 break;
242             case BluetoothDevice.METADATA_HARDWARE_VERSION:
243                 value = publicMetadata.hardware_version;
244                 break;
245             case BluetoothDevice.METADATA_COMPANION_APP:
246                 value = publicMetadata.companion_app;
247                 break;
248             case BluetoothDevice.METADATA_MAIN_ICON:
249                 value = publicMetadata.main_icon;
250                 break;
251             case BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET:
252                 value = publicMetadata.is_untethered_headset;
253                 break;
254             case BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON:
255                 value = publicMetadata.untethered_left_icon;
256                 break;
257             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON:
258                 value = publicMetadata.untethered_right_icon;
259                 break;
260             case BluetoothDevice.METADATA_UNTETHERED_CASE_ICON:
261                 value = publicMetadata.untethered_case_icon;
262                 break;
263             case BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY:
264                 value = publicMetadata.untethered_left_battery;
265                 break;
266             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY:
267                 value = publicMetadata.untethered_right_battery;
268                 break;
269             case BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY:
270                 value = publicMetadata.untethered_case_battery;
271                 break;
272             case BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING:
273                 value = publicMetadata.untethered_left_charging;
274                 break;
275             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING:
276                 value = publicMetadata.untethered_right_charging;
277                 break;
278             case BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING:
279                 value = publicMetadata.untethered_case_charging;
280                 break;
281             case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
282                 value = publicMetadata.enhanced_settings_ui_uri;
283                 break;
284             case BluetoothDevice.METADATA_DEVICE_TYPE:
285                 value = publicMetadata.device_type;
286                 break;
287             case BluetoothDevice.METADATA_MAIN_BATTERY:
288                 value = publicMetadata.main_battery;
289                 break;
290             case BluetoothDevice.METADATA_MAIN_CHARGING:
291                 value = publicMetadata.main_charging;
292                 break;
293             case BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD:
294                 value = publicMetadata.main_low_battery_threshold;
295                 break;
296             case BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD:
297                 value = publicMetadata.untethered_left_low_battery_threshold;
298                 break;
299             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD:
300                 value = publicMetadata.untethered_right_low_battery_threshold;
301                 break;
302             case BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD:
303                 value = publicMetadata.untethered_case_low_battery_threshold;
304                 break;
305         }
306         return value;
307     }
308 
getChangedCustomizedMeta()309     List<Integer> getChangedCustomizedMeta() {
310         List<Integer> list = new ArrayList<>();
311         for (int key = 0; key <= BluetoothDevice.getMaxMetadataKey(); key++) {
312             if (getCustomizedMeta(key) != null) {
313                 list.add(key);
314             }
315         }
316         return list;
317     }
318 
toString()319     public String toString() {
320         StringBuilder builder = new StringBuilder();
321         builder.append(address)
322             .append(" {profile connection policy(")
323             .append(profileConnectionPolicies)
324             .append("), optional codec(support=")
325             .append(a2dpSupportsOptionalCodecs)
326             .append("|enabled=")
327             .append(a2dpOptionalCodecsEnabled)
328             .append("), custom metadata(")
329             .append(publicMetadata)
330             .append(")}");
331 
332         return builder.toString();
333     }
334 }
335