1 /*
2  * Copyright (C) 2020 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.ims.rcs.uce.presence.pidfparser;
18 
19 import android.net.Uri;
20 import android.telephony.ims.RcsContactPresenceTuple;
21 import android.telephony.ims.RcsContactPresenceTuple.BasicStatus;
22 import android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities;
23 import android.telephony.ims.RcsContactUceCapability;
24 import android.text.TextUtils;
25 
26 import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Audio;
27 import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Duplex;
28 import com.android.ims.rcs.uce.presence.pidfparser.capabilities.ServiceCaps;
29 import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Video;
30 import com.android.ims.rcs.uce.presence.pidfparser.omapres.Description;
31 import com.android.ims.rcs.uce.presence.pidfparser.omapres.ServiceDescription;
32 import com.android.ims.rcs.uce.presence.pidfparser.omapres.ServiceId;
33 import com.android.ims.rcs.uce.presence.pidfparser.omapres.Version;
34 import com.android.ims.rcs.uce.presence.pidfparser.pidf.Basic;
35 import com.android.ims.rcs.uce.presence.pidfparser.pidf.Contact;
36 import com.android.ims.rcs.uce.presence.pidfparser.pidf.Presence;
37 import com.android.ims.rcs.uce.presence.pidfparser.pidf.Status;
38 import com.android.ims.rcs.uce.presence.pidfparser.pidf.Timestamp;
39 import com.android.ims.rcs.uce.presence.pidfparser.pidf.Tuple;
40 
41 import java.util.Arrays;
42 import java.util.List;
43 
44 /**
45  * The utils to help the PIDF parsing process.
46  */
47 public class PidfParserUtils {
48 
49     /*
50      * The resource terminated reason with NOT FOUND
51      */
52     private static String[] REQUEST_RESULT_REASON_NOT_FOUND = { "noresource", "rejected" };
53 
54     /**
55      * Convert the given class RcsContactUceCapability to the class Presence.
56      */
getPresence(RcsContactUceCapability capabilities)57     static Presence getPresence(RcsContactUceCapability capabilities) {
58         // Create "presence" element which is the root element of the pidf
59         Presence presence = new Presence(capabilities.getContactUri());
60 
61         List<RcsContactPresenceTuple> tupleList = capabilities.getCapabilityTuples();
62         if (tupleList == null || tupleList.isEmpty()) {
63             return presence;
64         }
65 
66         for (RcsContactPresenceTuple presenceTuple : tupleList) {
67             Tuple tupleElement = getTupleElement(presenceTuple);
68             if (tupleElement != null) {
69                 presence.addTuple(tupleElement);
70             }
71         }
72 
73         return presence;
74     }
75 
76     /**
77      * Convert the class from RcsContactPresenceTuple to the class Tuple
78      */
getTupleElement(RcsContactPresenceTuple presenceTuple)79     private static Tuple getTupleElement(RcsContactPresenceTuple presenceTuple) {
80         if (presenceTuple == null) {
81             return null;
82         }
83         Tuple tupleElement = new Tuple();
84 
85         // status element
86         handleTupleStatusElement(tupleElement, presenceTuple.getStatus());
87 
88         // service description element
89         handleTupleServiceDescriptionElement(tupleElement, presenceTuple.getServiceId(),
90                 presenceTuple.getServiceVersion(), presenceTuple.getServiceDescription());
91 
92         // service capabilities element
93         handleServiceCapsElement(tupleElement, presenceTuple.getServiceCapabilities());
94 
95         // contact element
96         handleTupleContactElement(tupleElement, presenceTuple.getContactUri());
97 
98         return tupleElement;
99     }
100 
handleTupleContactElement(Tuple tupleElement, Uri uri)101     private static void handleTupleContactElement(Tuple tupleElement, Uri uri) {
102         if (uri == null) {
103             return;
104         }
105         Contact contactElement = new Contact();
106         contactElement.setContact(uri.toString());
107         tupleElement.setContact(contactElement);
108     }
109 
handleTupleStatusElement(Tuple tupleElement, @BasicStatus String status)110     private static void handleTupleStatusElement(Tuple tupleElement, @BasicStatus String status) {
111         if (TextUtils.isEmpty(status)) {
112             return;
113         }
114         Basic basicElement = new Basic(status);
115         Status statusElement = new Status();
116         statusElement.setBasic(basicElement);
117         tupleElement.setStatus(statusElement);
118     }
119 
handleTupleServiceDescriptionElement(Tuple tupleElement, String serviceId, String version, String description)120     private static void handleTupleServiceDescriptionElement(Tuple tupleElement, String serviceId,
121             String version, String description) {
122         ServiceId serviceIdElement = null;
123         Version versionElement = null;
124         Description descriptionElement = null;
125 
126         // init serviceId element
127         if (!TextUtils.isEmpty(serviceId)) {
128             serviceIdElement = new ServiceId(serviceId);
129         }
130 
131         // init version element
132         if (!TextUtils.isEmpty(version)) {
133             String[] versionAry = version.split("\\.");
134             if (versionAry != null && versionAry.length == 2) {
135                 int majorVersion = Integer.parseInt(versionAry[0]);
136                 int minorVersion = Integer.parseInt(versionAry[1]);
137                 versionElement = new Version(majorVersion, minorVersion);
138             }
139         }
140 
141         // init description element
142         if (!TextUtils.isEmpty(description)) {
143             descriptionElement = new Description(description);
144         }
145 
146         // Add the Service Description element into the tuple
147         if (serviceIdElement != null && versionElement != null) {
148             ServiceDescription serviceDescription = new ServiceDescription();
149             serviceDescription.setServiceId(serviceIdElement);
150             serviceDescription.setVersion(versionElement);
151             if (descriptionElement != null) {
152                 serviceDescription.setDescription(descriptionElement);
153             }
154             tupleElement.setServiceDescription(serviceDescription);
155         }
156     }
157 
handleServiceCapsElement(Tuple tupleElement, ServiceCapabilities serviceCaps)158     private static void handleServiceCapsElement(Tuple tupleElement,
159             ServiceCapabilities serviceCaps) {
160         if (serviceCaps == null) {
161             return;
162         }
163 
164         ServiceCaps servCapsElement = new ServiceCaps();
165 
166         // Audio and Video element
167         Audio audioElement = new Audio(serviceCaps.isAudioCapable());
168         Video videoElement = new Video(serviceCaps.isVideoCapable());
169         servCapsElement.addElement(audioElement);
170         servCapsElement.addElement(videoElement);
171 
172         // Duplex element
173         List<String> supportedDuplexModes = serviceCaps.getSupportedDuplexModes();
174         List<String> UnsupportedDuplexModes = serviceCaps.getUnsupportedDuplexModes();
175         if ((supportedDuplexModes != null && !supportedDuplexModes.isEmpty()) ||
176                 (UnsupportedDuplexModes != null && !UnsupportedDuplexModes.isEmpty())) {
177             Duplex duplex = new Duplex();
178             if (!supportedDuplexModes.isEmpty()) {
179                 duplex.addSupportedType(supportedDuplexModes.get(0));
180             }
181             if (!UnsupportedDuplexModes.isEmpty()) {
182                 duplex.addNotSupportedType(UnsupportedDuplexModes.get(0));
183             }
184             servCapsElement.addElement(duplex);
185         }
186 
187         tupleElement.setServiceCaps(servCapsElement);
188     }
189 
190     /**
191      * Get the status from the given tuple.
192      */
getTupleStatus(Tuple tuple)193     public static String getTupleStatus(Tuple tuple) {
194         if (tuple == null) {
195             return null;
196         }
197         Status status = tuple.getStatus();
198         if (status != null) {
199             Basic basic = status.getBasic();
200             if (basic != null) {
201                 return basic.getValue();
202             }
203         }
204         return null;
205     }
206 
207     /**
208      * Get the service Id from the given tuple.
209      */
getTupleServiceId(Tuple tuple)210     public static String getTupleServiceId(Tuple tuple) {
211         if (tuple == null) {
212             return null;
213         }
214         ServiceDescription servDescription = tuple.getServiceDescription();
215         if (servDescription != null) {
216             ServiceId serviceId = servDescription.getServiceId();
217             if (serviceId != null) {
218                 return serviceId.getValue();
219             }
220         }
221         return null;
222     }
223 
224     /**
225      * Get the service version from the given tuple.
226      */
getTupleServiceVersion(Tuple tuple)227     public static String getTupleServiceVersion(Tuple tuple) {
228         if (tuple == null) {
229             return null;
230         }
231         ServiceDescription servDescription = tuple.getServiceDescription();
232         if (servDescription != null) {
233             Version version = servDescription.getVersion();
234             if (version != null) {
235                 return version.getValue();
236             }
237         }
238         return null;
239     }
240 
241     /**
242      * Get the service description from the given tuple.
243      */
getTupleServiceDescription(Tuple tuple)244     public static String getTupleServiceDescription(Tuple tuple) {
245         if (tuple == null) {
246             return null;
247         }
248         ServiceDescription servDescription = tuple.getServiceDescription();
249         if (servDescription != null) {
250             Description description = servDescription.getDescription();
251             if (description != null) {
252                 return description.getValue();
253             }
254         }
255         return null;
256     }
257 
258     /**
259      * Get the contact from the given tuple.
260      */
getTupleContact(Tuple tuple)261     public static String getTupleContact(Tuple tuple) {
262         if (tuple == null) {
263             return null;
264         }
265         Contact contact = tuple.getContact();
266         if (contact != null) {
267             return contact.getContact();
268         }
269         return null;
270     }
271 
272     /**
273      * Get the timestamp from the given tuple.
274      */
getTupleTimestamp(Tuple tuple)275     public static String getTupleTimestamp(Tuple tuple) {
276         if (tuple == null) {
277             return null;
278         }
279         Timestamp timestamp = tuple.getTimestamp();
280         if (timestamp != null) {
281             return timestamp.getValue();
282         }
283         return null;
284     }
285 
286     /**
287      * Get the malformed status from the given tuple.
288      */
getTupleMalformedStatus(Tuple tuple)289     public static boolean getTupleMalformedStatus(Tuple tuple) {
290         if (tuple == null) {
291             return false;
292         }
293         return tuple.getMalformed();
294     }
295 
296     /**
297      * Get the terminated capability which disable all the capabilities.
298      */
getTerminatedCapability(Uri contact, String reason)299     public static RcsContactUceCapability getTerminatedCapability(Uri contact, String reason) {
300         if (reason == null) reason = "";
301         int requestResult = (Arrays.stream(REQUEST_RESULT_REASON_NOT_FOUND)
302                     .anyMatch(reason::equalsIgnoreCase) == true) ?
303                             RcsContactUceCapability.REQUEST_RESULT_NOT_FOUND :
304                                     RcsContactUceCapability.REQUEST_RESULT_UNKNOWN;
305 
306         RcsContactUceCapability.PresenceBuilder builder =
307                 new RcsContactUceCapability.PresenceBuilder(
308                         contact, RcsContactUceCapability.SOURCE_TYPE_NETWORK, requestResult);
309         return builder.build();
310     }
311 
312     /**
313      * Get the RcsContactUceCapability instance which the request result is NOT FOUND.
314      */
getNotFoundContactCapabilities(Uri contact)315     public static RcsContactUceCapability getNotFoundContactCapabilities(Uri contact) {
316         RcsContactUceCapability.PresenceBuilder builder =
317                 new RcsContactUceCapability.PresenceBuilder(contact,
318                         RcsContactUceCapability.SOURCE_TYPE_NETWORK,
319                         RcsContactUceCapability.REQUEST_RESULT_NOT_FOUND);
320         return builder.build();
321     }
322 }
323