TelephonyTester.java revision 60c9dad26912093a7f95546d71909fce14039480
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 17package com.android.internal.telephony; 18 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.net.Uri; 24import android.os.BadParcelableException; 25import android.os.Build; 26import android.telephony.Rlog; 27import android.telephony.ServiceState; 28 29import com.android.ims.ImsCall; 30import com.android.ims.ImsCallProfile; 31import com.android.ims.ImsConferenceState; 32import com.android.ims.ImsExternalCallState; 33import com.android.ims.ImsReasonInfo; 34import com.android.internal.telephony.gsm.SuppServiceNotification; 35import com.android.internal.telephony.imsphone.ImsExternalCallTracker; 36import com.android.internal.telephony.imsphone.ImsPhone; 37import com.android.internal.telephony.imsphone.ImsPhoneCall; 38import com.android.internal.telephony.test.TestConferenceEventPackageParser; 39 40import java.io.File; 41import java.io.FileInputStream; 42import java.io.FileNotFoundException; 43import java.util.ArrayList; 44import java.util.List; 45 46/** 47 * Telephony tester receives the following intents where {name} is the phone name 48 * 49 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_detached 50 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_attached 51 * adb shell am broadcast -a com.android.internal.telephony.TestConferenceEventPackage -e filename 52 * test_filename.xml 53 * adb shell am broadcast -a com.android.internal.telephony.TestServiceState --ei data_rat 10 --ei 54 * data_roaming_type 3 55 * adb shell am broadcast -a com.android.internal.telephony.TestServiceState --es action reset 56 * 57 */ 58public class TelephonyTester { 59 private static final String LOG_TAG = "TelephonyTester"; 60 private static final boolean DBG = true; 61 62 /** 63 * Test-only intent used to send a test conference event package to the IMS framework. 64 */ 65 private static final String ACTION_TEST_CONFERENCE_EVENT_PACKAGE = 66 "com.android.internal.telephony.TestConferenceEventPackage"; 67 68 /** 69 * Test-only intent used to send a test dialog event package to the IMS framework. 70 */ 71 private static final String ACTION_TEST_DIALOG_EVENT_PACKAGE = 72 "com.android.internal.telephony.TestDialogEventPackage"; 73 74 private static final String EXTRA_FILENAME = "filename"; 75 private static final String EXTRA_STARTPACKAGE = "startPackage"; 76 private static final String EXTRA_SENDPACKAGE = "sendPackage"; 77 private static final String EXTRA_DIALOGID = "dialogId"; 78 private static final String EXTRA_NUMBER = "number"; 79 private static final String EXTRA_STATE = "state"; 80 private static final String EXTRA_CANPULL = "canPull"; 81 82 /** 83 * Test-only intent used to trigger supp service notification failure. 84 */ 85 private static final String ACTION_TEST_SUPP_SRVC_FAIL = 86 "com.android.internal.telephony.TestSuppSrvcFail"; 87 private static final String EXTRA_FAILURE_CODE = "failureCode"; 88 89 /** 90 * Test-only intent used to trigger the signalling which occurs when a handover to WIFI fails. 91 */ 92 private static final String ACTION_TEST_HANDOVER_FAIL = 93 "com.android.internal.telephony.TestHandoverFail"; 94 95 /** 96 * Test-only intent used to trigger signalling of a 97 * {@link com.android.internal.telephony.gsm.SuppServiceNotification} to the {@link ImsPhone}. 98 * Use {@link #EXTRA_CODE} to specify the 99 * {@link com.android.internal.telephony.gsm.SuppServiceNotification#code}. 100 */ 101 private static final String ACTION_TEST_SUPP_SRVC_NOTIFICATION = 102 "com.android.internal.telephony.TestSuppSrvcNotification"; 103 104 private static final String EXTRA_CODE = "code"; 105 106 107 private static final String ACTION_TEST_SERVICE_STATE = 108 "com.android.internal.telephony.TestServiceState"; 109 110 private static final String EXTRA_ACTION = "action"; 111 private static final String EXTRA_VOICE_RAT = "voice_rat"; 112 private static final String EXTRA_DATA_RAT = "data_rat"; 113 private static final String EXTRA_VOICE_REG_STATE = "voice_reg_state"; 114 private static final String EXTRA_DATA_REG_STATE = "data_reg_state"; 115 private static final String EXTRA_VOICE_ROAMING_TYPE = "voice_roaming_type"; 116 private static final String EXTRA_DATA_ROAMING_TYPE = "data_roaming_type"; 117 118 private static final String ACTION_RESET = "reset"; 119 120 private static List<ImsExternalCallState> mImsExternalCallStates = null; 121 122 private Intent mServiceStateTestIntent; 123 124 private Phone mPhone; 125 126 // The static intent receiver one for all instances and we assume this 127 // is running on the same thread as Dcc. 128 protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 129 @Override 130 public void onReceive(Context context, Intent intent) { 131 String action = intent.getAction(); 132 try { 133 if (DBG) log("sIntentReceiver.onReceive: action=" + action); 134 if (action.equals(mPhone.getActionDetached())) { 135 log("simulate detaching"); 136 mPhone.getServiceStateTracker().mDetachedRegistrants.notifyRegistrants(); 137 } else if (action.equals(mPhone.getActionAttached())) { 138 log("simulate attaching"); 139 mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants(); 140 } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) { 141 log("inject simulated conference event package"); 142 handleTestConferenceEventPackage(context, 143 intent.getStringExtra(EXTRA_FILENAME)); 144 } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) { 145 log("handle test dialog event package intent"); 146 handleTestDialogEventPackageIntent(intent); 147 } else if (action.equals(ACTION_TEST_SUPP_SRVC_FAIL)) { 148 log("handle test supp svc failed intent"); 149 handleSuppServiceFailedIntent(intent); 150 } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) { 151 log("handle handover fail test intent"); 152 handleHandoverFailedIntent(); 153 } else if (action.equals(ACTION_TEST_SUPP_SRVC_NOTIFICATION)) { 154 log("handle supp service notification test intent"); 155 sendTestSuppServiceNotification(intent); 156 } else if (action.equals(ACTION_TEST_SERVICE_STATE)) { 157 log("handle test service state changed intent"); 158 // Trigger the service state update. The replacement will be done in 159 // overrideServiceState(). 160 mServiceStateTestIntent = intent; 161 mPhone.getServiceStateTracker().sendEmptyMessage( 162 ServiceStateTracker.EVENT_NETWORK_STATE_CHANGED); 163 } else { 164 if (DBG) log("onReceive: unknown action=" + action); 165 } 166 } catch (BadParcelableException e) { 167 Rlog.w(LOG_TAG, e); 168 } 169 } 170 }; 171 172 TelephonyTester(Phone phone) { 173 mPhone = phone; 174 175 if (Build.IS_DEBUGGABLE) { 176 IntentFilter filter = new IntentFilter(); 177 178 filter.addAction(mPhone.getActionDetached()); 179 log("register for intent action=" + mPhone.getActionDetached()); 180 181 filter.addAction(mPhone.getActionAttached()); 182 log("register for intent action=" + mPhone.getActionAttached()); 183 184 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 185 log("register for intent action=" + ACTION_TEST_CONFERENCE_EVENT_PACKAGE); 186 filter.addAction(ACTION_TEST_CONFERENCE_EVENT_PACKAGE); 187 filter.addAction(ACTION_TEST_DIALOG_EVENT_PACKAGE); 188 filter.addAction(ACTION_TEST_SUPP_SRVC_FAIL); 189 filter.addAction(ACTION_TEST_HANDOVER_FAIL); 190 filter.addAction(ACTION_TEST_SUPP_SRVC_NOTIFICATION); 191 mImsExternalCallStates = new ArrayList<ImsExternalCallState>(); 192 } else { 193 filter.addAction(ACTION_TEST_SERVICE_STATE); 194 log("register for intent action=" + ACTION_TEST_SERVICE_STATE); 195 } 196 197 phone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone.getHandler()); 198 } 199 } 200 201 void dispose() { 202 if (Build.IS_DEBUGGABLE) { 203 mPhone.getContext().unregisterReceiver(mIntentReceiver); 204 } 205 } 206 207 private static void log(String s) { 208 Rlog.d(LOG_TAG, s); 209 } 210 211 private void handleSuppServiceFailedIntent(Intent intent) { 212 ImsPhone imsPhone = (ImsPhone) mPhone; 213 if (imsPhone == null) { 214 return; 215 } 216 int code = intent.getIntExtra(EXTRA_FAILURE_CODE, 0); 217 imsPhone.notifySuppServiceFailed(PhoneInternalInterface.SuppService.values()[code]); 218 } 219 220 private void handleHandoverFailedIntent() { 221 // Attempt to get the active IMS call 222 ImsPhone imsPhone = (ImsPhone) mPhone; 223 if (imsPhone == null) { 224 return; 225 } 226 227 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 228 if (imsPhoneCall == null) { 229 return; 230 } 231 232 ImsCall imsCall = imsPhoneCall.getImsCall(); 233 if (imsCall == null) { 234 return; 235 } 236 237 imsCall.getImsCallSessionListenerProxy().callSessionHandoverFailed(imsCall.getCallSession(), 238 ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, 239 new ImsReasonInfo()); 240 } 241 242 /** 243 * Handles request to send a test conference event package to the active Ims call. 244 * 245 * @see com.android.internal.telephony.test.TestConferenceEventPackageParser 246 * @param context The context. 247 * @param fileName The name of the test conference event package file to read. 248 */ 249 private void handleTestConferenceEventPackage(Context context, String fileName) { 250 // Attempt to get the active IMS call before parsing the test XML file. 251 ImsPhone imsPhone = (ImsPhone) mPhone; 252 if (imsPhone == null) { 253 return; 254 } 255 256 ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall(); 257 if (imsPhoneCall == null) { 258 return; 259 } 260 261 ImsCall imsCall = imsPhoneCall.getImsCall(); 262 if (imsCall == null) { 263 return; 264 } 265 266 File packageFile = new File(context.getFilesDir(), fileName); 267 final FileInputStream is; 268 try { 269 is = new FileInputStream(packageFile); 270 } catch (FileNotFoundException ex) { 271 log("Test conference event package file not found: " + packageFile.getAbsolutePath()); 272 return; 273 } 274 275 TestConferenceEventPackageParser parser = new TestConferenceEventPackageParser(is); 276 ImsConferenceState imsConferenceState = parser.parse(); 277 if (imsConferenceState == null) { 278 return; 279 } 280 281 imsCall.conferenceStateUpdated(imsConferenceState); 282 } 283 284 /** 285 * Handles intents containing test dialog event package data. 286 * 287 * @param intent 288 */ 289 private void handleTestDialogEventPackageIntent(Intent intent) { 290 ImsPhone imsPhone = (ImsPhone) mPhone; 291 if (imsPhone == null) { 292 return; 293 } 294 ImsExternalCallTracker externalCallTracker = imsPhone.getExternalCallTracker(); 295 if (externalCallTracker == null) { 296 return; 297 } 298 299 if (intent.hasExtra(EXTRA_STARTPACKAGE)) { 300 mImsExternalCallStates.clear(); 301 } else if (intent.hasExtra(EXTRA_SENDPACKAGE)) { 302 externalCallTracker.refreshExternalCallState(mImsExternalCallStates); 303 mImsExternalCallStates.clear(); 304 } else if (intent.hasExtra(EXTRA_DIALOGID)) { 305 ImsExternalCallState state = new ImsExternalCallState( 306 intent.getIntExtra(EXTRA_DIALOGID, 0), 307 Uri.parse(intent.getStringExtra(EXTRA_NUMBER)), 308 intent.getBooleanExtra(EXTRA_CANPULL, true), 309 intent.getIntExtra(EXTRA_STATE, 310 ImsExternalCallState.CALL_STATE_CONFIRMED), 311 ImsCallProfile.CALL_TYPE_VOICE, 312 false /* isHeld */ 313 ); 314 mImsExternalCallStates.add(state); 315 } 316 } 317 318 private void sendTestSuppServiceNotification(Intent intent) { 319 if (intent.hasExtra(EXTRA_CODE)) { 320 int code = intent.getIntExtra(EXTRA_CODE, -1); 321 ImsPhone imsPhone = (ImsPhone) mPhone; 322 if (imsPhone == null) { 323 return; 324 } 325 log("Test supp service notification:" + code); 326 SuppServiceNotification suppServiceNotification = new SuppServiceNotification(); 327 suppServiceNotification.code = code; 328 imsPhone.notifySuppSvcNotification(suppServiceNotification); 329 } 330 } 331 332 void overrideServiceState(ServiceState ss) { 333 if (mServiceStateTestIntent == null || ss == null) return; 334 if (mServiceStateTestIntent.hasExtra(EXTRA_ACTION) 335 && ACTION_RESET.equals(mServiceStateTestIntent.getStringExtra(EXTRA_ACTION))) { 336 log("Service state override reset"); 337 return; 338 } 339 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_REG_STATE)) { 340 ss.setVoiceRegState(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_REG_STATE, 341 ServiceState.RIL_REG_STATE_UNKNOWN)); 342 log("Override voice reg state with " + ss.getVoiceRegState()); 343 } 344 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_REG_STATE)) { 345 ss.setDataRegState(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_REG_STATE, 346 ServiceState.RIL_REG_STATE_UNKNOWN)); 347 log("Override data reg state with " + ss.getDataRegState()); 348 } 349 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_RAT)) { 350 ss.setRilVoiceRadioTechnology(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_RAT, 351 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)); 352 log("Override voice rat with " + ss.getRilVoiceRadioTechnology()); 353 } 354 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_RAT)) { 355 ss.setRilDataRadioTechnology(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_RAT, 356 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)); 357 log("Override data rat with " + ss.getRilDataRadioTechnology()); 358 } 359 if (mServiceStateTestIntent.hasExtra(EXTRA_VOICE_ROAMING_TYPE)) { 360 ss.setVoiceRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_VOICE_ROAMING_TYPE, 361 ServiceState.ROAMING_TYPE_UNKNOWN)); 362 log("Override voice roaming type with " + ss.getVoiceRoamingType()); 363 } 364 if (mServiceStateTestIntent.hasExtra(EXTRA_DATA_ROAMING_TYPE)) { 365 ss.setDataRoamingType(mServiceStateTestIntent.getIntExtra(EXTRA_DATA_ROAMING_TYPE, 366 ServiceState.ROAMING_TYPE_UNKNOWN)); 367 log("Override data roaming type with " + ss.getDataRoamingType()); 368 } 369 } 370}