1 /*
2  * Copyright (C) 2013 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;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.SharedPreferences;
24 import android.net.Uri;
25 import android.os.BadParcelableException;
26 import android.os.Build;
27 import android.preference.PreferenceManager;
28 import android.telephony.Rlog;
29 import android.telephony.ServiceState;
30 
31 import com.android.ims.ImsCall;
32 import com.android.ims.ImsCallProfile;
33 import com.android.ims.ImsConferenceState;
34 import com.android.ims.ImsExternalCallState;
35 import com.android.ims.ImsReasonInfo;
36 import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
37 import com.android.internal.telephony.imsphone.ImsPhone;
38 import com.android.internal.telephony.imsphone.ImsPhoneCall;
39 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
40 import com.android.internal.telephony.test.TestConferenceEventPackageParser;
41 
42 import java.io.File;
43 import java.io.FileInputStream;
44 import java.io.FileNotFoundException;
45 import java.util.ArrayList;
46 import java.util.List;
47 
48 /**
49  * Telephony tester receives the following intents where {name} is the phone name
50  *
51  * adb shell am broadcast -a com.android.internal.telephony.{name}.action_detached
52  * adb shell am broadcast -a com.android.internal.telephony.{name}.action_attached
53  * adb shell am broadcast -a com.android.internal.telephony.TestConferenceEventPackage -e filename
54  *      test_filename.xml
55  */
56 public class TelephonyTester {
57     private static final String LOG_TAG = "TelephonyTester";
58     private static final boolean DBG = true;
59 
60     /**
61      * Test-only intent used to send a test conference event package to the IMS framework.
62      */
63     private static final String ACTION_TEST_CONFERENCE_EVENT_PACKAGE =
64             "com.android.internal.telephony.TestConferenceEventPackage";
65 
66     /**
67      * Test-only intent used to send a test dialog event package to the IMS framework.
68      */
69     private static final String ACTION_TEST_DIALOG_EVENT_PACKAGE =
70             "com.android.internal.telephony.TestDialogEventPackage";
71 
72     private static final String EXTRA_FILENAME = "filename";
73     private static final String EXTRA_STARTPACKAGE = "startPackage";
74     private static final String EXTRA_SENDPACKAGE = "sendPackage";
75     private static final String EXTRA_DIALOGID = "dialogId";
76     private static final String EXTRA_NUMBER = "number";
77     private static final String EXTRA_STATE = "state";
78     private static final String EXTRA_CANPULL = "canPull";
79 
80     /**
81      * Test-only intent used to trigger the signalling which occurs when a handover to WIFI fails.
82      */
83     private static final String ACTION_TEST_HANDOVER_FAIL =
84             "com.android.internal.telephony.TestHandoverFail";
85 
86     private static List<ImsExternalCallState> mImsExternalCallStates = null;
87 
88     private Phone mPhone;
89 
90     // The static intent receiver one for all instances and we assume this
91     // is running on the same thread as Dcc.
92     protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
93             @Override
94         public void onReceive(Context context, Intent intent) {
95             String action = intent.getAction();
96             try {
97                 if (DBG) log("sIntentReceiver.onReceive: action=" + action);
98                 if (action.equals(mPhone.getActionDetached())) {
99                     log("simulate detaching");
100                     mPhone.getServiceStateTracker().mDetachedRegistrants.notifyRegistrants();
101                 } else if (action.equals(mPhone.getActionAttached())) {
102                     log("simulate attaching");
103                     mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants();
104                 } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) {
105                     log("inject simulated conference event package");
106                     handleTestConferenceEventPackage(context,
107                             intent.getStringExtra(EXTRA_FILENAME));
108                 } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) {
109                     log("handle test dialog event package intent");
110                     handleTestDialogEventPackageIntent(intent);
111                 } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) {
112                     log("handle handover fail test intent");
113                     handleHandoverFailedIntent();
114                 } else {
115                     if (DBG) log("onReceive: unknown action=" + action);
116                 }
117             } catch (BadParcelableException e) {
118                 Rlog.w(LOG_TAG, e);
119             }
120         }
121     };
122 
TelephonyTester(Phone phone)123     TelephonyTester(Phone phone) {
124         mPhone = phone;
125 
126         if (Build.IS_DEBUGGABLE) {
127             IntentFilter filter = new IntentFilter();
128 
129             filter.addAction(mPhone.getActionDetached());
130             log("register for intent action=" + mPhone.getActionDetached());
131 
132             filter.addAction(mPhone.getActionAttached());
133             log("register for intent action=" + mPhone.getActionAttached());
134 
135             if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
136                 log("register for intent action=" + ACTION_TEST_CONFERENCE_EVENT_PACKAGE);
137                 filter.addAction(ACTION_TEST_CONFERENCE_EVENT_PACKAGE);
138                 filter.addAction(ACTION_TEST_DIALOG_EVENT_PACKAGE);
139                 filter.addAction(ACTION_TEST_HANDOVER_FAIL);
140                 mImsExternalCallStates = new ArrayList<ImsExternalCallState>();
141             }
142 
143             phone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone.getHandler());
144         }
145     }
146 
dispose()147     void dispose() {
148         if (Build.IS_DEBUGGABLE) {
149             mPhone.getContext().unregisterReceiver(mIntentReceiver);
150         }
151     }
152 
log(String s)153     private static void log(String s) {
154         Rlog.d(LOG_TAG, s);
155     }
156 
handleHandoverFailedIntent()157     private void handleHandoverFailedIntent() {
158         // Attempt to get the active IMS call
159         ImsPhone imsPhone = (ImsPhone) mPhone;
160         if (imsPhone == null) {
161             return;
162         }
163 
164         ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall();
165         if (imsPhoneCall == null) {
166             return;
167         }
168 
169         ImsCall imsCall = imsPhoneCall.getImsCall();
170         if (imsCall == null) {
171             return;
172         }
173 
174         imsCall.getImsCallSessionListenerProxy().callSessionHandoverFailed(imsCall.getCallSession(),
175                 ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
176                 new ImsReasonInfo());
177     }
178 
179     /**
180      * Handles request to send a test conference event package to the active Ims call.
181      *
182      * @see com.android.internal.telephony.test.TestConferenceEventPackageParser
183      * @param context The context.
184      * @param fileName The name of the test conference event package file to read.
185      */
handleTestConferenceEventPackage(Context context, String fileName)186     private void handleTestConferenceEventPackage(Context context, String fileName) {
187         // Attempt to get the active IMS call before parsing the test XML file.
188         ImsPhone imsPhone = (ImsPhone) mPhone;
189         if (imsPhone == null) {
190             return;
191         }
192 
193         ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall();
194         if (imsPhoneCall == null) {
195             return;
196         }
197 
198         ImsCall imsCall = imsPhoneCall.getImsCall();
199         if (imsCall == null) {
200             return;
201         }
202 
203         File packageFile = new File(context.getFilesDir(), fileName);
204         final FileInputStream is;
205         try {
206             is = new FileInputStream(packageFile);
207         } catch (FileNotFoundException ex) {
208             log("Test conference event package file not found: " + packageFile.getAbsolutePath());
209             return;
210         }
211 
212         TestConferenceEventPackageParser parser = new TestConferenceEventPackageParser(is);
213         ImsConferenceState imsConferenceState = parser.parse();
214         if (imsConferenceState == null) {
215             return;
216         }
217 
218         imsCall.conferenceStateUpdated(imsConferenceState);
219     }
220 
221     /**
222      * Handles intents containing test dialog event package data.
223      *
224      * @param intent
225      */
handleTestDialogEventPackageIntent(Intent intent)226     private void handleTestDialogEventPackageIntent(Intent intent) {
227         ImsPhone imsPhone = (ImsPhone) mPhone;
228         if (imsPhone == null) {
229             return;
230         }
231         ImsExternalCallTracker externalCallTracker = imsPhone.getExternalCallTracker();
232         if (externalCallTracker == null) {
233             return;
234         }
235 
236         if (intent.hasExtra(EXTRA_STARTPACKAGE)) {
237             mImsExternalCallStates.clear();
238         } else if (intent.hasExtra(EXTRA_SENDPACKAGE)) {
239             externalCallTracker.refreshExternalCallState(mImsExternalCallStates);
240             mImsExternalCallStates.clear();
241         } else if (intent.hasExtra(EXTRA_DIALOGID)) {
242             ImsExternalCallState state = new ImsExternalCallState(
243                     intent.getIntExtra(EXTRA_DIALOGID, 0),
244                     Uri.parse(intent.getStringExtra(EXTRA_NUMBER)),
245                     intent.getBooleanExtra(EXTRA_CANPULL, true),
246                     intent.getIntExtra(EXTRA_STATE,
247                             ImsExternalCallState.CALL_STATE_CONFIRMED),
248                     ImsCallProfile.CALL_TYPE_VOICE,
249                     false /* isHeld */
250                     );
251             mImsExternalCallStates.add(state);
252         }
253     }
254 }
255