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 import android.bluetooth.BluetoothUtils;
25 
26 import androidx.annotation.NonNull;
27 import androidx.room.Embedded;
28 import androidx.room.Entity;
29 import androidx.room.PrimaryKey;
30 
31 import com.android.internal.annotations.VisibleForTesting;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 @Entity(tableName = "metadata")
37 @VisibleForTesting
38 public class Metadata {
39     @PrimaryKey @NonNull private String address;
40 
41     public boolean migrated;
42 
43     @Embedded public ProfilePrioritiesEntity profileConnectionPolicies;
44 
45     @Embedded @NonNull public CustomizedMetadataEntity publicMetadata;
46 
47     public @OptionalCodecsSupportStatus int a2dpSupportsOptionalCodecs;
48     public @OptionalCodecsPreferenceStatus int a2dpOptionalCodecsEnabled;
49 
50     public long last_active_time;
51     public boolean is_active_a2dp_device;
52 
53     public boolean isActiveHfpDevice;
54 
55     @Embedded public AudioPolicyEntity audioPolicyMetadata;
56 
57     /**
58      * The preferred profile to be used for {@link BluetoothDevice#AUDIO_MODE_OUTPUT_ONLY}. This can
59      * be either {@link BluetoothProfile#A2DP} or {@link BluetoothProfile#LE_AUDIO}. This value is
60      * only used if the remote device supports both A2DP and LE Audio and both transports are
61      * connected and active.
62      */
63     public int preferred_output_only_profile;
64 
65     /**
66      * The preferred profile to be used for {@link BluetoothDevice#AUDIO_MODE_DUPLEX}. This can be
67      * either {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#LE_AUDIO}. This value is
68      * only used if the remote device supports both HFP and LE Audio and both transports are
69      * connected and active.
70      */
71     public int preferred_duplex_profile;
72 
73     /** This is used to indicate whether device's active audio policy */
74     public int active_audio_device_policy;
75 
Metadata(String address)76     Metadata(String address) {
77         this(address, false, false);
78     }
79 
Metadata(String address, boolean isActiveA2dp, boolean isActiveHfp)80     private Metadata(String address, boolean isActiveA2dp, boolean isActiveHfp) {
81         this.address = address;
82         migrated = false;
83         profileConnectionPolicies = new ProfilePrioritiesEntity();
84         publicMetadata = new CustomizedMetadataEntity();
85         a2dpSupportsOptionalCodecs = BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN;
86         a2dpOptionalCodecsEnabled = BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN;
87         last_active_time = MetadataDatabase.sCurrentConnectionNumber++;
88         is_active_a2dp_device = isActiveA2dp;
89         isActiveHfpDevice = isActiveHfp;
90         audioPolicyMetadata = new AudioPolicyEntity();
91         preferred_output_only_profile = 0;
92         preferred_duplex_profile = 0;
93         active_audio_device_policy = BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
94     }
95 
96     static final class Builder {
97         final String mAddress;
98         boolean mIsActiveA2dpDevice = false;
99         boolean mIsActiveHfpDevice = false;
100 
Builder(String address)101         Builder(String address) {
102             mAddress = address;
103         }
104 
setActiveA2dp()105         Builder setActiveA2dp() {
106             mIsActiveA2dpDevice = true;
107             return this;
108         }
109 
setActiveHfp()110         Builder setActiveHfp() {
111             mIsActiveHfpDevice = true;
112             return this;
113         }
114 
build()115         Metadata build() {
116             return new Metadata(mAddress, mIsActiveA2dpDevice, mIsActiveHfpDevice);
117         }
118     }
119 
120     @VisibleForTesting
getAddress()121     public String getAddress() {
122         return address;
123     }
124 
125     /**
126      * Returns the anonymized hardware address. The first three octets will be suppressed for
127      * anonymization.
128      *
129      * <p>For example, "XX:XX:XX:AA:BB:CC".
130      *
131      * @return Anonymized bluetooth hardware address as string
132      */
133     @NonNull
getAnonymizedAddress()134     public String getAnonymizedAddress() {
135         return BluetoothUtils.toAnonymizedAddress(address);
136     }
137 
setProfileConnectionPolicy(int profile, int connectionPolicy)138     void setProfileConnectionPolicy(int profile, int connectionPolicy) {
139         // We no longer support BluetoothProfile.PRIORITY_AUTO_CONNECT and are merging it into
140         // BluetoothProfile.CONNECTION_POLICY_ALLOWED
141         if (connectionPolicy > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
142             connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED;
143         }
144 
145         switch (profile) {
146             case BluetoothProfile.A2DP:
147                 profileConnectionPolicies.a2dp_connection_policy = connectionPolicy;
148                 break;
149             case BluetoothProfile.A2DP_SINK:
150                 profileConnectionPolicies.a2dp_sink_connection_policy = connectionPolicy;
151                 break;
152             case BluetoothProfile.HEADSET:
153                 profileConnectionPolicies.hfp_connection_policy = connectionPolicy;
154                 break;
155             case BluetoothProfile.HEADSET_CLIENT:
156                 profileConnectionPolicies.hfp_client_connection_policy = connectionPolicy;
157                 break;
158             case BluetoothProfile.HID_HOST:
159                 profileConnectionPolicies.hid_host_connection_policy = connectionPolicy;
160                 break;
161             case BluetoothProfile.PAN:
162                 profileConnectionPolicies.pan_connection_policy = connectionPolicy;
163                 break;
164             case BluetoothProfile.PBAP:
165                 profileConnectionPolicies.pbap_connection_policy = connectionPolicy;
166                 break;
167             case BluetoothProfile.PBAP_CLIENT:
168                 profileConnectionPolicies.pbap_client_connection_policy = connectionPolicy;
169                 break;
170             case BluetoothProfile.MAP:
171                 profileConnectionPolicies.map_connection_policy = connectionPolicy;
172                 break;
173             case BluetoothProfile.MAP_CLIENT:
174                 profileConnectionPolicies.map_client_connection_policy = connectionPolicy;
175                 break;
176             case BluetoothProfile.SAP:
177                 profileConnectionPolicies.sap_connection_policy = connectionPolicy;
178                 break;
179             case BluetoothProfile.HEARING_AID:
180                 profileConnectionPolicies.hearing_aid_connection_policy = connectionPolicy;
181                 break;
182             case BluetoothProfile.HAP_CLIENT:
183                 profileConnectionPolicies.hap_client_connection_policy = connectionPolicy;
184                 break;
185             case BluetoothProfile.LE_AUDIO:
186                 profileConnectionPolicies.le_audio_connection_policy = connectionPolicy;
187                 break;
188             case BluetoothProfile.VOLUME_CONTROL:
189                 profileConnectionPolicies.volume_control_connection_policy = connectionPolicy;
190                 break;
191             case BluetoothProfile.CSIP_SET_COORDINATOR:
192                 profileConnectionPolicies.csip_set_coordinator_connection_policy = connectionPolicy;
193                 break;
194             case BluetoothProfile.LE_CALL_CONTROL:
195                 profileConnectionPolicies.le_call_control_connection_policy = connectionPolicy;
196                 break;
197             case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT:
198                 profileConnectionPolicies.bass_client_connection_policy = connectionPolicy;
199                 break;
200             case BluetoothProfile.BATTERY:
201                 profileConnectionPolicies.battery_connection_policy = connectionPolicy;
202                 break;
203             default:
204                 throw new IllegalArgumentException("invalid profile " + profile);
205         }
206     }
207 
208     @VisibleForTesting
getProfileConnectionPolicy(int profile)209     public int getProfileConnectionPolicy(int profile) {
210         switch (profile) {
211             case BluetoothProfile.A2DP:
212                 return profileConnectionPolicies.a2dp_connection_policy;
213             case BluetoothProfile.A2DP_SINK:
214                 return profileConnectionPolicies.a2dp_sink_connection_policy;
215             case BluetoothProfile.HEADSET:
216                 return profileConnectionPolicies.hfp_connection_policy;
217             case BluetoothProfile.HEADSET_CLIENT:
218                 return profileConnectionPolicies.hfp_client_connection_policy;
219             case BluetoothProfile.HID_HOST:
220                 return profileConnectionPolicies.hid_host_connection_policy;
221             case BluetoothProfile.PAN:
222                 return profileConnectionPolicies.pan_connection_policy;
223             case BluetoothProfile.PBAP:
224                 return profileConnectionPolicies.pbap_connection_policy;
225             case BluetoothProfile.PBAP_CLIENT:
226                 return profileConnectionPolicies.pbap_client_connection_policy;
227             case BluetoothProfile.MAP:
228                 return profileConnectionPolicies.map_connection_policy;
229             case BluetoothProfile.MAP_CLIENT:
230                 return profileConnectionPolicies.map_client_connection_policy;
231             case BluetoothProfile.SAP:
232                 return profileConnectionPolicies.sap_connection_policy;
233             case BluetoothProfile.HEARING_AID:
234                 return profileConnectionPolicies.hearing_aid_connection_policy;
235             case BluetoothProfile.HAP_CLIENT:
236                 return profileConnectionPolicies.hap_client_connection_policy;
237             case BluetoothProfile.LE_AUDIO:
238                 return profileConnectionPolicies.le_audio_connection_policy;
239             case BluetoothProfile.VOLUME_CONTROL:
240                 return profileConnectionPolicies.volume_control_connection_policy;
241             case BluetoothProfile.CSIP_SET_COORDINATOR:
242                 return profileConnectionPolicies.csip_set_coordinator_connection_policy;
243             case BluetoothProfile.LE_CALL_CONTROL:
244                 return profileConnectionPolicies.le_call_control_connection_policy;
245             case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT:
246                 return profileConnectionPolicies.bass_client_connection_policy;
247             case BluetoothProfile.BATTERY:
248                 return profileConnectionPolicies.battery_connection_policy;
249         }
250         return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
251     }
252 
setCustomizedMeta(int key, byte[] value)253     void setCustomizedMeta(int key, byte[] value) {
254         switch (key) {
255             case BluetoothDevice.METADATA_MANUFACTURER_NAME:
256                 publicMetadata.manufacturer_name = value;
257                 break;
258             case BluetoothDevice.METADATA_MODEL_NAME:
259                 publicMetadata.model_name = value;
260                 break;
261             case BluetoothDevice.METADATA_SOFTWARE_VERSION:
262                 publicMetadata.software_version = value;
263                 break;
264             case BluetoothDevice.METADATA_HARDWARE_VERSION:
265                 publicMetadata.hardware_version = value;
266                 break;
267             case BluetoothDevice.METADATA_COMPANION_APP:
268                 publicMetadata.companion_app = value;
269                 break;
270             case BluetoothDevice.METADATA_MAIN_ICON:
271                 publicMetadata.main_icon = value;
272                 break;
273             case BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET:
274                 publicMetadata.is_untethered_headset = value;
275                 break;
276             case BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON:
277                 publicMetadata.untethered_left_icon = value;
278                 break;
279             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON:
280                 publicMetadata.untethered_right_icon = value;
281                 break;
282             case BluetoothDevice.METADATA_UNTETHERED_CASE_ICON:
283                 publicMetadata.untethered_case_icon = value;
284                 break;
285             case BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY:
286                 publicMetadata.untethered_left_battery = value;
287                 break;
288             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY:
289                 publicMetadata.untethered_right_battery = value;
290                 break;
291             case BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY:
292                 publicMetadata.untethered_case_battery = value;
293                 break;
294             case BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING:
295                 publicMetadata.untethered_left_charging = value;
296                 break;
297             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING:
298                 publicMetadata.untethered_right_charging = value;
299                 break;
300             case BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING:
301                 publicMetadata.untethered_case_charging = value;
302                 break;
303             case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
304                 publicMetadata.enhanced_settings_ui_uri = value;
305                 break;
306             case BluetoothDevice.METADATA_DEVICE_TYPE:
307                 publicMetadata.device_type = value;
308                 break;
309             case BluetoothDevice.METADATA_MAIN_BATTERY:
310                 publicMetadata.main_battery = value;
311                 break;
312             case BluetoothDevice.METADATA_MAIN_CHARGING:
313                 publicMetadata.main_charging = value;
314                 break;
315             case BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD:
316                 publicMetadata.main_low_battery_threshold = value;
317                 break;
318             case BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD:
319                 publicMetadata.untethered_left_low_battery_threshold = value;
320                 break;
321             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD:
322                 publicMetadata.untethered_right_low_battery_threshold = value;
323                 break;
324             case BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD:
325                 publicMetadata.untethered_case_low_battery_threshold = value;
326                 break;
327             case BluetoothDevice.METADATA_SPATIAL_AUDIO:
328                 publicMetadata.spatial_audio = value;
329                 break;
330             case BluetoothDevice.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS:
331                 publicMetadata.fastpair_customized = value;
332                 break;
333             case BluetoothDevice.METADATA_LE_AUDIO:
334                 publicMetadata.le_audio = value;
335                 break;
336             case BluetoothDevice.METADATA_GMCS_CCCD:
337                 publicMetadata.gmcs_cccd = value;
338                 break;
339             case BluetoothDevice.METADATA_GTBS_CCCD:
340                 publicMetadata.gtbs_cccd = value;
341                 break;
342             case BluetoothDevice.METADATA_EXCLUSIVE_MANAGER:
343                 publicMetadata.exclusive_manager = value;
344                 break;
345         }
346     }
347 
348     @VisibleForTesting
getCustomizedMeta(int key)349     public byte[] getCustomizedMeta(int key) {
350         byte[] value = null;
351         switch (key) {
352             case BluetoothDevice.METADATA_MANUFACTURER_NAME:
353                 value = publicMetadata.manufacturer_name;
354                 break;
355             case BluetoothDevice.METADATA_MODEL_NAME:
356                 value = publicMetadata.model_name;
357                 break;
358             case BluetoothDevice.METADATA_SOFTWARE_VERSION:
359                 value = publicMetadata.software_version;
360                 break;
361             case BluetoothDevice.METADATA_HARDWARE_VERSION:
362                 value = publicMetadata.hardware_version;
363                 break;
364             case BluetoothDevice.METADATA_COMPANION_APP:
365                 value = publicMetadata.companion_app;
366                 break;
367             case BluetoothDevice.METADATA_MAIN_ICON:
368                 value = publicMetadata.main_icon;
369                 break;
370             case BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET:
371                 value = publicMetadata.is_untethered_headset;
372                 break;
373             case BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON:
374                 value = publicMetadata.untethered_left_icon;
375                 break;
376             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON:
377                 value = publicMetadata.untethered_right_icon;
378                 break;
379             case BluetoothDevice.METADATA_UNTETHERED_CASE_ICON:
380                 value = publicMetadata.untethered_case_icon;
381                 break;
382             case BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY:
383                 value = publicMetadata.untethered_left_battery;
384                 break;
385             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY:
386                 value = publicMetadata.untethered_right_battery;
387                 break;
388             case BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY:
389                 value = publicMetadata.untethered_case_battery;
390                 break;
391             case BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING:
392                 value = publicMetadata.untethered_left_charging;
393                 break;
394             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING:
395                 value = publicMetadata.untethered_right_charging;
396                 break;
397             case BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING:
398                 value = publicMetadata.untethered_case_charging;
399                 break;
400             case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
401                 value = publicMetadata.enhanced_settings_ui_uri;
402                 break;
403             case BluetoothDevice.METADATA_DEVICE_TYPE:
404                 value = publicMetadata.device_type;
405                 break;
406             case BluetoothDevice.METADATA_MAIN_BATTERY:
407                 value = publicMetadata.main_battery;
408                 break;
409             case BluetoothDevice.METADATA_MAIN_CHARGING:
410                 value = publicMetadata.main_charging;
411                 break;
412             case BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD:
413                 value = publicMetadata.main_low_battery_threshold;
414                 break;
415             case BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD:
416                 value = publicMetadata.untethered_left_low_battery_threshold;
417                 break;
418             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD:
419                 value = publicMetadata.untethered_right_low_battery_threshold;
420                 break;
421             case BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD:
422                 value = publicMetadata.untethered_case_low_battery_threshold;
423                 break;
424             case BluetoothDevice.METADATA_SPATIAL_AUDIO:
425                 value = publicMetadata.spatial_audio;
426                 break;
427             case BluetoothDevice.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS:
428                 value = publicMetadata.fastpair_customized;
429                 break;
430             case BluetoothDevice.METADATA_LE_AUDIO:
431                 value = publicMetadata.le_audio;
432                 break;
433             case BluetoothDevice.METADATA_GMCS_CCCD:
434                 value = publicMetadata.gmcs_cccd;
435                 break;
436             case BluetoothDevice.METADATA_GTBS_CCCD:
437                 value = publicMetadata.gtbs_cccd;
438                 break;
439             case BluetoothDevice.METADATA_EXCLUSIVE_MANAGER:
440                 value = publicMetadata.exclusive_manager;
441                 break;
442         }
443         return value;
444     }
445 
getChangedCustomizedMeta()446     List<Integer> getChangedCustomizedMeta() {
447         List<Integer> list = new ArrayList<>();
448         for (int key = 0; key <= BluetoothDevice.getMaxMetadataKey(); key++) {
449             if (getCustomizedMeta(key) != null) {
450                 list.add(key);
451             }
452         }
453         return list;
454     }
455 
toString()456     public String toString() {
457         StringBuilder builder = new StringBuilder();
458         builder.append(getAnonymizedAddress())
459                 .append(" last_active_time=" + last_active_time)
460                 .append(" {profile connection policy(")
461                 .append(profileConnectionPolicies)
462                 .append("), optional codec(support=")
463                 .append(a2dpSupportsOptionalCodecs)
464                 .append("|enabled=")
465                 .append(a2dpOptionalCodecsEnabled)
466                 .append("), isActiveHfpDevice (")
467                 .append(isActiveHfpDevice)
468                 .append("), custom metadata(")
469                 .append(publicMetadata)
470                 .append("), hfp client audio policy(")
471                 .append(audioPolicyMetadata)
472                 .append(")}");
473 
474         return builder.toString();
475     }
476 }
477