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             default:
114                 throw new IllegalArgumentException("invalid profile " + profile);
115         }
116     }
117 
getProfileConnectionPolicy(int profile)118     int getProfileConnectionPolicy(int profile) {
119         switch (profile) {
120             case BluetoothProfile.A2DP:
121                 return profileConnectionPolicies.a2dp_connection_policy;
122             case BluetoothProfile.A2DP_SINK:
123                 return profileConnectionPolicies.a2dp_sink_connection_policy;
124             case BluetoothProfile.HEADSET:
125                 return profileConnectionPolicies.hfp_connection_policy;
126             case BluetoothProfile.HEADSET_CLIENT:
127                 return profileConnectionPolicies.hfp_client_connection_policy;
128             case BluetoothProfile.HID_HOST:
129                 return profileConnectionPolicies.hid_host_connection_policy;
130             case BluetoothProfile.PAN:
131                 return profileConnectionPolicies.pan_connection_policy;
132             case BluetoothProfile.PBAP:
133                 return profileConnectionPolicies.pbap_connection_policy;
134             case BluetoothProfile.PBAP_CLIENT:
135                 return profileConnectionPolicies.pbap_client_connection_policy;
136             case BluetoothProfile.MAP:
137                 return profileConnectionPolicies.map_connection_policy;
138             case BluetoothProfile.MAP_CLIENT:
139                 return profileConnectionPolicies.map_client_connection_policy;
140             case BluetoothProfile.SAP:
141                 return profileConnectionPolicies.sap_connection_policy;
142             case BluetoothProfile.HEARING_AID:
143                 return profileConnectionPolicies.hearing_aid_connection_policy;
144         }
145         return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
146     }
147 
setCustomizedMeta(int key, byte[] value)148     void setCustomizedMeta(int key, byte[] value) {
149         switch (key) {
150             case BluetoothDevice.METADATA_MANUFACTURER_NAME:
151                 publicMetadata.manufacturer_name = value;
152                 break;
153             case BluetoothDevice.METADATA_MODEL_NAME:
154                 publicMetadata.model_name = value;
155                 break;
156             case BluetoothDevice.METADATA_SOFTWARE_VERSION:
157                 publicMetadata.software_version = value;
158                 break;
159             case BluetoothDevice.METADATA_HARDWARE_VERSION:
160                 publicMetadata.hardware_version = value;
161                 break;
162             case BluetoothDevice.METADATA_COMPANION_APP:
163                 publicMetadata.companion_app = value;
164                 break;
165             case BluetoothDevice.METADATA_MAIN_ICON:
166                 publicMetadata.main_icon = value;
167                 break;
168             case BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET:
169                 publicMetadata.is_untethered_headset = value;
170                 break;
171             case BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON:
172                 publicMetadata.untethered_left_icon = value;
173                 break;
174             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON:
175                 publicMetadata.untethered_right_icon = value;
176                 break;
177             case BluetoothDevice.METADATA_UNTETHERED_CASE_ICON:
178                 publicMetadata.untethered_case_icon = value;
179                 break;
180             case BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY:
181                 publicMetadata.untethered_left_battery = value;
182                 break;
183             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY:
184                 publicMetadata.untethered_right_battery = value;
185                 break;
186             case BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY:
187                 publicMetadata.untethered_case_battery = value;
188                 break;
189             case BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING:
190                 publicMetadata.untethered_left_charging = value;
191                 break;
192             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING:
193                 publicMetadata.untethered_right_charging = value;
194                 break;
195             case BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING:
196                 publicMetadata.untethered_case_charging = value;
197                 break;
198             case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
199                 publicMetadata.enhanced_settings_ui_uri = value;
200                 break;
201         }
202     }
203 
getCustomizedMeta(int key)204     byte[] getCustomizedMeta(int key) {
205         byte[] value = null;
206         switch (key) {
207             case BluetoothDevice.METADATA_MANUFACTURER_NAME:
208                 value = publicMetadata.manufacturer_name;
209                 break;
210             case BluetoothDevice.METADATA_MODEL_NAME:
211                 value = publicMetadata.model_name;
212                 break;
213             case BluetoothDevice.METADATA_SOFTWARE_VERSION:
214                 value = publicMetadata.software_version;
215                 break;
216             case BluetoothDevice.METADATA_HARDWARE_VERSION:
217                 value = publicMetadata.hardware_version;
218                 break;
219             case BluetoothDevice.METADATA_COMPANION_APP:
220                 value = publicMetadata.companion_app;
221                 break;
222             case BluetoothDevice.METADATA_MAIN_ICON:
223                 value = publicMetadata.main_icon;
224                 break;
225             case BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET:
226                 value = publicMetadata.is_untethered_headset;
227                 break;
228             case BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON:
229                 value = publicMetadata.untethered_left_icon;
230                 break;
231             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON:
232                 value = publicMetadata.untethered_right_icon;
233                 break;
234             case BluetoothDevice.METADATA_UNTETHERED_CASE_ICON:
235                 value = publicMetadata.untethered_case_icon;
236                 break;
237             case BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY:
238                 value = publicMetadata.untethered_left_battery;
239                 break;
240             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY:
241                 value = publicMetadata.untethered_right_battery;
242                 break;
243             case BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY:
244                 value = publicMetadata.untethered_case_battery;
245                 break;
246             case BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING:
247                 value = publicMetadata.untethered_left_charging;
248                 break;
249             case BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING:
250                 value = publicMetadata.untethered_right_charging;
251                 break;
252             case BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING:
253                 value = publicMetadata.untethered_case_charging;
254                 break;
255             case BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI:
256                 value = publicMetadata.enhanced_settings_ui_uri;
257                 break;
258         }
259         return value;
260     }
261 
getChangedCustomizedMeta()262     List<Integer> getChangedCustomizedMeta() {
263         List<Integer> list = new ArrayList<>();
264         if (publicMetadata.manufacturer_name != null) {
265             list.add(BluetoothDevice.METADATA_MANUFACTURER_NAME);
266         }
267         if (publicMetadata.model_name != null) {
268             list.add(BluetoothDevice.METADATA_MODEL_NAME);
269         }
270         if (publicMetadata.software_version != null) {
271             list.add(BluetoothDevice.METADATA_SOFTWARE_VERSION);
272         }
273         if (publicMetadata.hardware_version != null) {
274             list.add(BluetoothDevice.METADATA_HARDWARE_VERSION);
275         }
276         if (publicMetadata.companion_app != null) {
277             list.add(BluetoothDevice.METADATA_COMPANION_APP);
278         }
279         if (publicMetadata.main_icon != null) {
280             list.add(BluetoothDevice.METADATA_MAIN_ICON);
281         }
282         if (publicMetadata.is_untethered_headset != null) {
283             list.add(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
284         }
285         if (publicMetadata.untethered_left_icon != null) {
286             list.add(BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON);
287         }
288         if (publicMetadata.untethered_right_icon != null) {
289             list.add(BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON);
290         }
291         if (publicMetadata.untethered_case_icon != null) {
292             list.add(BluetoothDevice.METADATA_UNTETHERED_CASE_ICON);
293         }
294         if (publicMetadata.untethered_left_battery != null) {
295             list.add(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY);
296         }
297         if (publicMetadata.untethered_right_battery != null) {
298             list.add(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY);
299         }
300         if (publicMetadata.untethered_case_battery != null) {
301             list.add(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY);
302         }
303         if (publicMetadata.untethered_left_charging != null) {
304             list.add(BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING);
305         }
306         if (publicMetadata.untethered_right_charging != null) {
307             list.add(BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING);
308         }
309         if (publicMetadata.untethered_case_charging != null) {
310             list.add(BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING);
311         }
312         if (publicMetadata.enhanced_settings_ui_uri != null) {
313             list.add(BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
314         }
315         return list;
316     }
317 
toString()318     public String toString() {
319         StringBuilder builder = new StringBuilder();
320         builder.append(address)
321             .append(" {profile connection policy(")
322             .append(profileConnectionPolicies)
323             .append("), optional codec(support=")
324             .append(a2dpSupportsOptionalCodecs)
325             .append("|enabled=")
326             .append(a2dpOptionalCodecsEnabled)
327             .append("), custom metadata(")
328             .append(publicMetadata)
329             .append(")}");
330 
331         return builder.toString();
332     }
333 }
334