1 /*
2  * Copyright 2024 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.pbapclient;
18 
19 import android.accounts.Account;
20 import android.bluetooth.BluetoothDevice;
21 
22 import java.nio.ByteBuffer;
23 import java.util.List;
24 
25 public class Utils {
26     // VCard Version strings
27     public static final String VERSION_21 = "2.1";
28     public static final String VERSION_30 = "3.0";
29     public static final String VERSION_UNSUPPORTED = "4.0";
30 
31     // Constants for creating VCard strings.
32     private static final String N = "N";
33     private static final String FN = "FN";
34     private static final String ADDR = "ADR;TYPE=HOME";
35     private static final String CELL = "TEL;TYPE=CELL";
36     private static final String EMAIL = "EMAIL;INTERNET";
37     private static final String TEL = "TEL;TYPE=0";
38 
39     // Constants for creating a call history entry
40     public static final String MISSED_CALL = "MISSED";
41     public static final String INCOMING_CALL = "RECEIVED";
42     public static final String OUTGOING_CALL = "DIALED";
43     private static final String CALL_HISTORY = "X-IRMC-CALL-DATETIME";
44 
45     public static final String ACCOUNT_TYPE = "com.android.bluetooth.pbapclient";
46 
getAccountForDevice(BluetoothDevice device)47     public static Account getAccountForDevice(BluetoothDevice device) {
48         return new Account(device.getAddress(), ACCOUNT_TYPE);
49     }
50 
51     /**
52      * Group a list of VCard entries or Call History entries into a full phonebook
53      *
54      * @param vcardStrings The list of VCard or call history strings to group into a phonebook
55      * @return A string representation of the entire phonebook
56      */
createPhonebook(List<String> vcardStrings)57     public static String createPhonebook(List<String> vcardStrings) {
58         StringBuilder sb = new StringBuilder();
59         for (String vcard : vcardStrings) {
60             sb.append(vcard).append("\n");
61         }
62         return sb.toString();
63     }
64 
65     /**
66      * Create a VCard string fit for parsing
67      *
68      * <p>A null value in any field outside of name fields will cause it to be dropped from the
69      * entry.
70      *
71      * @param version the version of the VCard you want to create
72      * @param first the first name of the VCard you want to create
73      * @param last the last name of the VCard you want to create
74      * @param phone the phone number of the VCard you want to create
75      * @param addr the address of the VCard you want to create
76      * @param email the email of the VCard you want to create
77      * @return a VCard string, built with the information provided
78      */
createVcard( String version, String first, String last, String phone, String addr, String email)79     public static String createVcard(
80             String version, String first, String last, String phone, String addr, String email) {
81         StringBuilder sb = new StringBuilder();
82         sb.append("BEGIN:VCARD\n");
83         sb.append("VERSION:").append(version).append("\n");
84 
85         // Friendly name
86         sb.append(FN).append(":").append(first).append(" ").append(last).append("\n");
87 
88         // Full name: “LastName;FirstName;MiddleName;Prefix;Suffix”
89         sb.append(N).append(":").append(last).append(";").append(first).append("\n");
90 
91         if (phone != null) {
92             sb.append(CELL).append(":").append(phone).append("\n");
93         }
94 
95         if (addr != null) {
96             sb.append(ADDR).append(":").append(addr).append("\n");
97         }
98 
99         if (email != null) {
100             sb.append(EMAIL).append(":").append(email).append("\n");
101         }
102 
103         sb.append("END:VCARD");
104 
105         return sb.toString();
106     }
107 
108     /**
109      * Create a call history entry string fit for parsing
110      *
111      * <p>A call history entry is a VCard with special fields to carry the type of call and the time
112      * the call occurred
113      *
114      * @param version the version of the call history entry you want to create
115      * @param type the type of the call history entry you want to create
116      * @param time the time of the call history entry, in the format "YYYYMMDDTHHMMSS"
117      * @param first the first name of the person who was called
118      * @param last the last name of the person who was called
119      * @param phone the phone number of the person who was called
120      */
createCallHistory( String version, String type, String time, String first, String last, String phone)121     public static String createCallHistory(
122             String version, String type, String time, String first, String last, String phone) {
123         StringBuilder sb = new StringBuilder();
124         sb.append("BEGIN:VCARD\n");
125         sb.append("VERSION:").append(version).append("\n");
126 
127         if (VERSION_30.equals(version)) {
128             sb.append(FN).append(":").append(first).append(" ").append(last).append("\n");
129         }
130 
131         sb.append(N).append(":").append(last).append(";").append(first).append("\n");
132 
133         sb.append(TEL).append(":").append(phone).append("\n");
134 
135         // Time format: YYYYMMDDTHHMMSS -> 20050320T100000
136         if (VERSION_30.equals(version)) {
137             sb.append(CALL_HISTORY)
138                     .append(";TYPE=")
139                     .append(type)
140                     .append(":")
141                     .append(time)
142                     .append("\n");
143         } else {
144             sb.append(CALL_HISTORY).append(";").append(type).append(":").append(time).append("\n");
145         }
146 
147         sb.append("END:VCARD");
148 
149         return sb.toString();
150     }
151 
shortToByteArray(short s)152     public static byte[] shortToByteArray(short s) {
153         ByteBuffer ret = ByteBuffer.allocate(2);
154         ret.putShort(s);
155         return ret.array();
156     }
157 
longToByteArray(long l)158     public static byte[] longToByteArray(long l) {
159         ByteBuffer ret = ByteBuffer.allocate(16);
160         ret.putLong(0); // Most significant bytes
161         ret.putLong(l); // Least significant bytes
162         return ret.array();
163     }
164 }
165