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