10d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn/* 20d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Copyright (C) 2014 The Android Open Source Project 30d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * 40d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Licensed under the Apache License, Version 2.0 (the "License"); 50d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * you may not use this file except in compliance with the License. 60d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * You may obtain a copy of the License at 70d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * 80d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * http://www.apache.org/licenses/LICENSE-2.0 90d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * 100d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Unless required by applicable law or agreed to in writing, software 110d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * distributed under the License is distributed on an "AS IS" BASIS, 120d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * See the License for the specific language governing permissions and 140d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * limitations under the License 150d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn */ 160d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 170d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnpackage com.android.internal.telephony.test; 180d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 190d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport com.android.ims.ImsConferenceState; 200d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport com.android.internal.util.XmlUtils; 210d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 220d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport org.xmlpull.v1.XmlPullParser; 230d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport org.xmlpull.v1.XmlPullParserException; 240d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 250d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport android.os.Bundle; 260d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport android.util.Log; 270d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport android.util.Xml; 280d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 290d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport java.io.BufferedInputStream; 300d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport java.io.IOException; 310d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnimport java.io.InputStream; 320d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 330d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn/** 340d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Implements a basic XML parser used to parse test IMS conference event packages which can be 350d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * injected into the IMS framework via the {@link com.android.internal.telephony.TelephonyTester}. 360d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <pre> 370d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * {@code 380d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <xml> 390d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <participant> 400d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <user>tel:+16505551212</user> 410d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <display-text>Joe Q. Public</display-text> 420d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <endpoint>sip:+16505551212@ims-test-provider.com</endpoint> 430d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <status>connected</status> 440d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * </participant> 450d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * </xml> 460d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * } 470d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * </pre> 480d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <p> 490d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Note: This XML format is similar to the information stored in the 500d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * {@link com.android.ims.ImsConferenceState} parcelable. The {@code status} values expected in the 510d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * XML are those found in the {@code ImsConferenceState} class (e.g. 520d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * {@link com.android.ims.ImsConferenceState#STATUS_CONNECTED}). 530d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <p> 540d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Place a file formatted similar to above in /data/data/com.android.phone/files/ and invoke the 550d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * following command while you have an ongoing IMS call: 560d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * <pre> 570d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * adb shell am broadcast 580d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * -a com.android.internal.telephony.TestConferenceEventPackage 590d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * -e filename test.xml 600d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * </pre> 610d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn */ 620d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunnpublic class TestConferenceEventPackageParser { 630d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn private static final String LOG_TAG = "TestConferenceEventPackageParser"; 640d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn private static final String PARTICIPANT_TAG = "participant"; 650d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 660d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn /** 670d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * The XML input stream to parse. 680d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn */ 690d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn private InputStream mInputStream; 700d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 710d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn /** 720d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Constructs an input of the conference event package parser for the given input stream. 730d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * 740d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * @param inputStream The input stream. 750d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn */ 760d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn public TestConferenceEventPackageParser(InputStream inputStream) { 770d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn mInputStream = inputStream; 780d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 790d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 800d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn /** 810d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Parses the conference event package XML file and returns an 820d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * {@link com.android.ims.ImsConferenceState} instance containing the participants described in 830d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * the XML file. 840d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * 850d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * @return The {@link com.android.ims.ImsConferenceState} instance. 860d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn */ 870d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn public ImsConferenceState parse() { 880d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn ImsConferenceState conferenceState = new ImsConferenceState(); 890d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 900d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn XmlPullParser parser; 910d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn try { 920d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser = Xml.newPullParser(); 930d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser.setInput(mInputStream, null); 940d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser.nextTag(); 950d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 960d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn int outerDepth = parser.getDepth(); 970d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn while (XmlUtils.nextElementWithin(parser, outerDepth)) { 980d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn if (parser.getName().equals(PARTICIPANT_TAG)) { 990d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.v(LOG_TAG, "Found participant."); 1000d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Bundle participant = parseParticipant(parser); 1010d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn conferenceState.mParticipants.put(participant.getString( 1020d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn ImsConferenceState.ENDPOINT), participant); 1030d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1040d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1050d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } catch (IOException | XmlPullParserException e) { 1060d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.e(LOG_TAG, "Failed to read test conference event package from XML file", e); 1070d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn return null; 1080d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } finally { 1090d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn try { 1100d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn mInputStream.close(); 1110d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } catch (IOException e) { 1120d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.e(LOG_TAG, "Failed to close test conference event package InputStream", e); 1130d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn return null; 1140d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1150d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1160d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1170d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn return conferenceState; 1180d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1190d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1200d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn /** 1210d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * Parses a participant record from a conference event package XML file. 1220d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * 1230d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * @param parser The XML parser. 1240d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn * @return {@link Bundle} containing the participant information. 1250d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn */ 1260d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn private Bundle parseParticipant(XmlPullParser parser) 1270d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn throws IOException, XmlPullParserException { 1280d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Bundle bundle = new Bundle(); 1290d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1300d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn String user = ""; 1310d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn String displayText = ""; 1320d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn String endpoint = ""; 1330d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn String status = ""; 1340d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1350d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn int outerDepth = parser.getDepth(); 1360d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1370d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn if (parser.getName().equals(ImsConferenceState.USER)) { 1380d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser.next(); 1390d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn user = parser.getText(); 1400d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } else if (parser.getName().equals(ImsConferenceState.DISPLAY_TEXT)) { 1410d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser.next(); 1420d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn displayText = parser.getText(); 1430d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } else if (parser.getName().equals(ImsConferenceState.ENDPOINT)) { 1440d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser.next(); 1450d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn endpoint = parser.getText(); 1460d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } else if (parser.getName().equals(ImsConferenceState.STATUS)) { 1470d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn parser.next(); 1480d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn status = parser.getText(); 1490d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1500d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1510d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1520d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.v(LOG_TAG, "User: "+user); 1530d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.v(LOG_TAG, "DisplayText: "+displayText); 1540d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.v(LOG_TAG, "Endpoint: "+endpoint); 1550d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn Log.v(LOG_TAG, "Status: "+status); 1560d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1570d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn bundle.putString(ImsConferenceState.USER, user); 1580d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn bundle.putString(ImsConferenceState.DISPLAY_TEXT, displayText); 1590d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn bundle.putString(ImsConferenceState.ENDPOINT, endpoint); 1600d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn bundle.putString(ImsConferenceState.STATUS, status); 1610d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn 1620d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn return bundle; 1630d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn } 1640d4f1fe3137cc4a76fc2bb0dac80c68220e53550Tyler Gunn} 165