1 /*
2  * Copyright (C) 2014 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.internal.telephony.test;
18 
19 import android.os.Bundle;
20 import android.telephony.ims.ImsConferenceState;
21 import android.util.Log;
22 import android.util.Xml;
23 
24 import com.android.internal.telephony.util.XmlUtils;
25 
26 import org.xmlpull.v1.XmlPullParser;
27 import org.xmlpull.v1.XmlPullParserException;
28 
29 import java.io.IOException;
30 import java.io.InputStream;
31 
32 /**
33  * Implements a basic XML parser used to parse test IMS conference event packages which can be
34  * injected into the IMS framework via the {@link com.android.internal.telephony.TelephonyTester}.
35  * <pre>
36  * {@code
37  * <xml>
38  *     <participant>
39  *         <user>tel:+16505551212</user>
40  *         <display-text>Joe Q. Public</display-text>
41  *         <endpoint>sip:+16505551212@ims-test-provider.com</endpoint>
42  *         <status>connected</status>
43  *     </participant>
44  * </xml>
45  * }
46  * </pre>
47  * <p>
48  * Note: This XML format is similar to the information stored in the
49  * {@link ImsConferenceState} parcelable.  The {@code status} values expected in the
50  * XML are those found in the {@code ImsConferenceState} class (e.g.
51  * {@link ImsConferenceState#STATUS_CONNECTED}).
52  * <p>
53  * Place a file formatted similar to above in /data/data/com.android.phone/files/ and invoke the
54  * following command while you have an ongoing IMS call:
55  * <pre>
56  *     adb shell am broadcast
57  *          -a com.android.internal.telephony.TestConferenceEventPackage
58  *          -e filename test.xml
59  * </pre>
60  */
61 public class TestConferenceEventPackageParser {
62     private static final String LOG_TAG = "TestConferenceEventPackageParser";
63     private static final String PARTICIPANT_TAG = "participant";
64 
65     /**
66      * The XML input stream to parse.
67      */
68     private InputStream mInputStream;
69 
70     /**
71      * Constructs an input of the conference event package parser for the given input stream.
72      *
73      * @param inputStream The input stream.
74      */
TestConferenceEventPackageParser(InputStream inputStream)75     public TestConferenceEventPackageParser(InputStream inputStream) {
76         mInputStream = inputStream;
77     }
78 
79     /**
80      * Parses the conference event package XML file and returns an
81      * {@link ImsConferenceState} instance containing the participants described in
82      * the XML file.
83      *
84      * @return The {@link ImsConferenceState} instance.
85      */
parse()86     public ImsConferenceState parse() {
87         ImsConferenceState conferenceState = new ImsConferenceState();
88 
89         XmlPullParser parser;
90         try {
91             parser = Xml.newPullParser();
92             parser.setInput(mInputStream, null);
93             parser.nextTag();
94 
95             int outerDepth = parser.getDepth();
96             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
97                 if (parser.getName().equals(PARTICIPANT_TAG)) {
98                     Log.v(LOG_TAG, "Found participant.");
99                     Bundle participant = parseParticipant(parser);
100                     conferenceState.mParticipants.put(participant.getString(
101                             ImsConferenceState.ENDPOINT), participant);
102                 }
103             }
104         } catch (IOException | XmlPullParserException e) {
105             Log.e(LOG_TAG, "Failed to read test conference event package from XML file", e);
106             return null;
107         } finally {
108             try {
109                 mInputStream.close();
110             } catch (IOException e) {
111                 Log.e(LOG_TAG, "Failed to close test conference event package InputStream", e);
112                 return null;
113             }
114         }
115 
116         return conferenceState;
117     }
118 
119     /**
120      * Parses a participant record from a conference event package XML file.
121      *
122      * @param parser The XML parser.
123      * @return {@link Bundle} containing the participant information.
124      */
parseParticipant(XmlPullParser parser)125     private Bundle parseParticipant(XmlPullParser parser)
126             throws IOException, XmlPullParserException {
127         Bundle bundle = new Bundle();
128 
129         String user = "";
130         String displayText = "";
131         String endpoint = "";
132         String status = "";
133 
134         int outerDepth = parser.getDepth();
135         while (XmlUtils.nextElementWithin(parser, outerDepth)) {
136             if (parser.getName().equals(ImsConferenceState.USER)) {
137                 parser.next();
138                 user = parser.getText();
139             } else if (parser.getName().equals(ImsConferenceState.DISPLAY_TEXT)) {
140                 parser.next();
141                 displayText = parser.getText();
142             }  else if (parser.getName().equals(ImsConferenceState.ENDPOINT)) {
143                 parser.next();
144                 endpoint = parser.getText();
145             }  else if (parser.getName().equals(ImsConferenceState.STATUS)) {
146                 parser.next();
147                 status = parser.getText();
148             }
149         }
150 
151         Log.v(LOG_TAG, "User: "+user);
152         Log.v(LOG_TAG, "DisplayText: "+displayText);
153         Log.v(LOG_TAG, "Endpoint: "+endpoint);
154         Log.v(LOG_TAG, "Status: "+status);
155 
156         bundle.putString(ImsConferenceState.USER, user);
157         bundle.putString(ImsConferenceState.DISPLAY_TEXT, displayText);
158         bundle.putString(ImsConferenceState.ENDPOINT, endpoint);
159         bundle.putString(ImsConferenceState.STATUS, status);
160 
161         return bundle;
162     }
163 }
164