/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony.imsphone; import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE; import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyChar; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.Activity; import android.app.IApplicationThread; import android.content.BroadcastReceiver; import android.content.IIntentReceiver; import android.content.Intent; import android.os.AsyncResult; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.os.PersistableBundle; import android.os.SystemProperties; import android.support.test.filters.FlakyTest; import android.telephony.CarrierConfigManager; import android.test.suitebuilder.annotation.SmallTest; import com.android.ims.ImsCallProfile; import com.android.ims.ImsEcbmStateListener; import com.android.ims.ImsManager; import com.android.ims.ImsReasonInfo; import com.android.ims.ImsUtInterface; import com.android.internal.telephony.Call; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.Connection; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.gsm.SuppServiceNotification; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import java.util.List; public class ImsPhoneTest extends TelephonyTest { @Mock private ImsPhoneCall mForegroundCall; @Mock private ImsPhoneCall mBackgroundCall; @Mock private ImsPhoneCall mRingingCall; @Mock private Handler mTestHandler; @Mock Connection mConnection; @Mock ImsUtInterface mImsUtInterface; private ImsPhone mImsPhoneUT; private ImsPhoneTestHandler mImsPhoneTestHandler; private boolean mDoesRilSendMultipleCallRing; private static final int EVENT_SUPP_SERVICE_NOTIFICATION = 1; private static final int EVENT_SUPP_SERVICE_FAILED = 2; private static final int EVENT_INCOMING_RING = 3; private static final int EVENT_EMERGENCY_CALLBACK_MODE_EXIT = 4; private class ImsPhoneTestHandler extends HandlerThread { private ImsPhoneTestHandler(String name) { super(name); } @Override public void onLooperPrepared() { mImsPhoneUT = new ImsPhone(mContext, mNotifier, mPhone, true); setReady(true); } } @Before public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); mImsCT.mForegroundCall = mForegroundCall; mImsCT.mBackgroundCall = mBackgroundCall; mImsCT.mRingingCall = mRingingCall; doReturn(Call.State.IDLE).when(mForegroundCall).getState(); doReturn(Call.State.IDLE).when(mBackgroundCall).getState(); doReturn(Call.State.IDLE).when(mRingingCall).getState(); mContextFixture.putBooleanResource(com.android.internal.R.bool.config_voice_capable, true); mImsPhoneTestHandler = new ImsPhoneTestHandler(TAG); mImsPhoneTestHandler.start(); waitUntilReady(); mDoesRilSendMultipleCallRing = SystemProperties.getBoolean( TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true); replaceInstance(Handler.class, "mLooper", mTestHandler, mImsPhoneUT.getLooper()); replaceInstance(Phone.class, "mLooper", mPhone, mImsPhoneUT.getLooper()); mImsPhoneUT.registerForSuppServiceNotification(mTestHandler, EVENT_SUPP_SERVICE_NOTIFICATION, null); mImsPhoneUT.registerForSuppServiceFailed(mTestHandler, EVENT_SUPP_SERVICE_FAILED, null); mImsPhoneUT.registerForIncomingRing(mTestHandler, EVENT_INCOMING_RING, null); doReturn(mImsUtInterface).when(mImsCT).getUtInterface(); } @After public void tearDown() throws Exception { mImsPhoneUT = null; mImsPhoneTestHandler.quit(); super.tearDown(); } @Test @SmallTest public void testHandleInCallMmiCommandCallDeflection() throws Exception { doReturn(Call.State.INCOMING).when(mRingingCall).getState(); // dial string length > 1 assertEquals(false, mImsPhoneUT.handleInCallMmiCommands("00")); // ringing call is not idle assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("0")); verify(mImsCT).rejectCall(); // ringing is idle, background call is not idle doReturn(Call.State.IDLE).when(mRingingCall).getState(); doReturn(Call.State.ACTIVE).when(mBackgroundCall).getState(); assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("0")); verify(mImsCT).hangup(mBackgroundCall); } @Test @SmallTest public void testHandleInCallMmiCommandCallWaiting() throws Exception { doReturn(Call.State.ACTIVE).when(mForegroundCall).getState(); // dial string length > 2 assertEquals(false, mImsPhoneUT.handleInCallMmiCommands("100")); // dial string length > 1 assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("10")); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); assertEquals(EVENT_SUPP_SERVICE_FAILED, messageArgumentCaptor.getValue().what); assertEquals(Phone.SuppService.HANGUP, ((AsyncResult)messageArgumentCaptor.getValue().obj).result); // foreground call is not idle assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("1")); verify(mImsCT).hangup(any(ImsPhoneCall.class)); // foreground call is idle doReturn(Call.State.IDLE).when(mForegroundCall).getState(); doReturn(Call.State.INCOMING).when(mRingingCall).getState(); assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("1")); verify(mImsCT).switchWaitingOrHoldingAndActive(); } @Test @SmallTest public void testHandleInCallMmiCommandCallHold() throws Exception { doReturn(Call.State.ACTIVE).when(mForegroundCall).getState(); // dial string length > 2 assertEquals(false, mImsPhoneUT.handleInCallMmiCommands("200")); // dial string length > 1 assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("20")); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); assertEquals(EVENT_SUPP_SERVICE_FAILED, messageArgumentCaptor.getValue().what); assertEquals(Phone.SuppService.SEPARATE, ((AsyncResult) messageArgumentCaptor.getValue().obj).result); // ringing call is idle assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2")); verify(mImsCT).switchWaitingOrHoldingAndActive(); // ringing call is not idle doReturn(Call.State.INCOMING).when(mRingingCall).getState(); assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2")); verify(mImsCT).acceptCall(ImsCallProfile.CALL_TYPE_VOICE); } @Test @SmallTest public void testHandleInCallMmiCommandMultiparty() { doReturn(Call.State.ACTIVE).when(mForegroundCall).getState(); // dial string length > 1 assertEquals(false, mImsPhoneUT.handleInCallMmiCommands("30")); // dial string length == 1 assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("3")); verify(mImsCT).conference(); } @Test @SmallTest public void testHandleInCallMmiCommandCallEct() { doReturn(Call.State.ACTIVE).when(mForegroundCall).getState(); // dial string length > 1 assertEquals(false, mImsPhoneUT.handleInCallMmiCommands("40")); // dial string length == 1 assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("4")); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); assertEquals(EVENT_SUPP_SERVICE_FAILED, messageArgumentCaptor.getValue().what); assertEquals(Phone.SuppService.TRANSFER, ((AsyncResult) messageArgumentCaptor.getValue().obj).result); } @Test @SmallTest public void testHandleInCallMmiCommandCallCcbs() { doReturn(Call.State.ACTIVE).when(mForegroundCall).getState(); // dial string length > 1 assertEquals(false, mImsPhoneUT.handleInCallMmiCommands("50")); // dial string length == 1 assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("5")); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); assertEquals(EVENT_SUPP_SERVICE_FAILED, messageArgumentCaptor.getValue().what); assertEquals(Phone.SuppService.UNKNOWN, ((AsyncResult)messageArgumentCaptor.getValue().obj).result); } @Test @SmallTest public void testDispose() { // add MMI to verify that dispose removes it mImsPhoneUT.sendUssdResponse("1234"); verify(mImsCT).sendUSSD(eq("1234"), any(Message.class)); List list = mImsPhoneUT.getPendingMmiCodes(); assertNotNull(list); assertEquals(1, list.size()); mImsPhoneUT.dispose(); assertEquals(0, list.size()); verify(mImsCT).dispose(); verify(mSST).unregisterForDataRegStateOrRatChanged(mImsPhoneUT); } @Test @SmallTest public void testGettersAndPassThroughs() throws Exception { Message msg = mTestHandler.obtainMessage(); assertNotNull(mImsPhoneUT.getServiceState()); assertEquals(mImsCT, mImsPhoneUT.getCallTracker()); mImsPhoneUT.acceptCall(0); verify(mImsCT).acceptCall(0); mImsPhoneUT.rejectCall(); verify(mImsCT).rejectCall(); mImsPhoneUT.switchHoldingAndActive(); verify(mImsCT).switchWaitingOrHoldingAndActive(); assertEquals(false, mImsPhoneUT.canConference()); doReturn(true).when(mImsCT).canConference(); assertEquals(true, mImsPhoneUT.canConference()); verify(mImsCT, times(2)).canConference(); assertEquals(false, mImsPhoneUT.canDial()); doReturn(true).when(mImsCT).canDial(); assertEquals(true, mImsPhoneUT.canDial()); verify(mImsCT, times(2)).canDial(); mImsPhoneUT.conference(); verify(mImsCT).conference(); mImsPhoneUT.clearDisconnected(); verify(mImsCT).clearDisconnected(); assertEquals(false, mImsPhoneUT.canTransfer()); doReturn(true).when(mImsCT).canTransfer(); assertEquals(true, mImsPhoneUT.canTransfer()); verify(mImsCT, times(2)).canTransfer(); mImsPhoneUT.explicitCallTransfer(); verify(mImsCT).explicitCallTransfer(); assertEquals(mForegroundCall, mImsPhoneUT.getForegroundCall()); assertEquals(mBackgroundCall, mImsPhoneUT.getBackgroundCall()); assertEquals(mRingingCall, mImsPhoneUT.getRingingCall()); mImsPhoneUT.notifyNewRingingConnection(mConnection); verify(mPhone).notifyNewRingingConnectionP(mConnection); mImsPhoneUT.notifyForVideoCapabilityChanged(true); verify(mPhone).notifyForVideoCapabilityChanged(true); mImsPhoneUT.setMute(true); verify(mImsCT).setMute(true); mImsPhoneUT.setUiTTYMode(1234, null); verify(mImsCT).setUiTTYMode(1234, null); doReturn(false).when(mImsCT).getMute(); assertEquals(false, mImsPhoneUT.getMute()); doReturn(true).when(mImsCT).getMute(); assertEquals(true, mImsPhoneUT.getMute()); verify(mImsCT, times(2)).getMute(); doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); assertEquals(PhoneConstants.State.IDLE, mImsPhoneUT.getState()); doReturn(PhoneConstants.State.RINGING).when(mImsCT).getState(); assertEquals(PhoneConstants.State.RINGING, mImsPhoneUT.getState()); mImsPhoneUT.sendUSSD("1234", msg); verify(mImsCT).sendUSSD("1234", msg); mImsPhoneUT.cancelUSSD(); verify(mImsCT).cancelUSSD(); } @Test @SmallTest public void testSuppServiceNotification() { SuppServiceNotification ssn = new SuppServiceNotification(); mImsPhoneUT.notifySuppSvcNotification(ssn); // verify registrants are notified ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mTestHandler, times(1)).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); Message message = messageArgumentCaptor.getValue(); assertEquals(EVENT_SUPP_SERVICE_NOTIFICATION, message.what); assertEquals(ssn, ((AsyncResult) message.obj).result); assertEquals(null, ((AsyncResult) message.obj).userObj); assertEquals(null, ((AsyncResult) message.obj).exception); // verify no notification is received after unregister (verify() still sees only 1 // notification) mImsPhoneUT.unregisterForSuppServiceNotification(mTestHandler); mImsPhoneUT.notifySuppSvcNotification(ssn); verify(mTestHandler, times(1)).sendMessageAtTime(any(Message.class), anyLong()); } @Test @SmallTest public void testDial() throws Exception { String dialString = "1234567890"; int videoState = 0; mImsPhoneUT.dial(dialString, videoState); verify(mImsCT).dial(dialString, videoState, null); } @Test @SmallTest public void testDtmf() { // case 1 doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); mImsPhoneUT.sendDtmf('-'); verify(mImsCT, times(0)).sendDtmf(anyChar(), nullable(Message.class)); // case 2 mImsPhoneUT.sendDtmf('0'); verify(mImsCT, times(0)).sendDtmf(eq('0'), nullable(Message.class)); // case 3 doReturn(PhoneConstants.State.OFFHOOK).when(mImsCT).getState(); mImsPhoneUT.sendDtmf('-'); verify(mImsCT, times(0)).sendDtmf(eq('0'), nullable(Message.class)); // case 4 mImsPhoneUT.sendDtmf('0'); verify(mImsCT, times(1)).sendDtmf(anyChar(), nullable(Message.class)); mImsPhoneUT.startDtmf('-'); verify(mImsCT, times(0)).startDtmf(anyChar()); mImsPhoneUT.startDtmf('0'); verify(mImsCT, times(1)).startDtmf('0'); mImsPhoneUT.stopDtmf(); verify(mImsCT).stopDtmf(); } @Test @SmallTest public void testIncomingRing() { doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState(); mImsPhoneUT.notifyIncomingRing(); waitForMs(100); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mTestHandler, times(1)).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); Message message = messageArgumentCaptor.getValue(); assertEquals(EVENT_INCOMING_RING, message.what); } @Test @SmallTest public void testOutgoingCallerIdDisplay() throws Exception { Message msg = mTestHandler.obtainMessage(); mImsPhoneUT.getOutgoingCallerIdDisplay(msg); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mImsUtInterface).queryCLIR(messageArgumentCaptor.capture()); assertEquals(msg, messageArgumentCaptor.getValue().obj); mImsPhoneUT.setOutgoingCallerIdDisplay(1234, msg); verify(mImsUtInterface).updateCLIR(eq(1234), messageArgumentCaptor.capture()); assertEquals(msg, messageArgumentCaptor.getValue().obj); } @FlakyTest @Test @Ignore public void testCallForwardingOption() throws Exception { Message msg = mTestHandler.obtainMessage(); mImsPhoneUT.getCallForwardingOption(CF_REASON_UNCONDITIONAL, msg); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mImsUtInterface).queryCallForward(eq(ImsUtInterface.CDIV_CF_UNCONDITIONAL), (String) eq(null), messageArgumentCaptor.capture()); assertEquals(msg, messageArgumentCaptor.getValue().obj); mImsPhoneUT.setCallForwardingOption(CF_ACTION_ENABLE, CF_REASON_UNCONDITIONAL, "1234", 0, msg); verify(mImsUtInterface).updateCallForward(eq(ImsUtInterface.ACTION_ACTIVATION), eq(ImsUtInterface.CDIV_CF_UNCONDITIONAL), eq("1234"), eq(CommandsInterface.SERVICE_CLASS_VOICE), eq(0), eq(msg)); } @Test @SmallTest public void testCallWaiting() throws Exception { Message msg = mTestHandler.obtainMessage(); mImsPhoneUT.getCallWaiting(msg); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mImsUtInterface).queryCallWaiting(messageArgumentCaptor.capture()); assertEquals(msg, messageArgumentCaptor.getValue().obj); mImsPhoneUT.setCallWaiting(true, msg); verify(mImsUtInterface).updateCallWaiting(eq(true), eq(CommandsInterface.SERVICE_CLASS_VOICE), messageArgumentCaptor.capture()); assertEquals(msg, messageArgumentCaptor.getValue().obj); } @Test @SmallTest public void testCellBarring() throws Exception { Message msg = mTestHandler.obtainMessage(); mImsPhoneUT.getCallBarring(CommandsInterface.CB_FACILITY_BAOC, msg); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); verify(mImsUtInterface).queryCallBarring(eq(ImsUtInterface.CB_BAOC), messageArgumentCaptor.capture()); assertEquals(msg, messageArgumentCaptor.getValue().obj); mImsPhoneUT.setCallBarring(CommandsInterface.CB_FACILITY_BAOIC, true, "abc", msg); verify(mImsUtInterface).updateCallBarring(eq(ImsUtInterface.CB_BOIC), eq(CommandsInterface.CF_ACTION_ENABLE), messageArgumentCaptor.capture(), (String[]) eq(null)); assertEquals(msg, messageArgumentCaptor.getValue().obj); mImsPhoneUT.setCallBarring(CommandsInterface.CB_FACILITY_BAOICxH, false, "abc", msg); verify(mImsUtInterface).updateCallBarring(eq(ImsUtInterface.CB_BOIC_EXHC), eq(CommandsInterface.CF_ACTION_DISABLE), messageArgumentCaptor.capture(), (String[])eq(null)); assertEquals(msg, messageArgumentCaptor.getValue().obj); } @FlakyTest @Test @Ignore public void testEcbm() throws Exception { ImsEcbmStateListener imsEcbmStateListener = mImsPhoneUT.getImsEcbmStateListener(); // verify handling of emergency callback mode imsEcbmStateListener.onECBMEntered(); // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED ArgumentCaptor intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mIActivityManager, atLeast(1)).broadcastIntent(eq((IApplicationThread)null), intentArgumentCaptor.capture(), eq((String)null), eq((IIntentReceiver)null), eq(Activity.RESULT_OK), eq((String)null), eq((Bundle)null), eq((String[])null), anyInt(), eq((Bundle)null), eq(false), eq(true), anyInt()); Intent intent = intentArgumentCaptor.getValue(); assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction()); assertEquals(true, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, false)); // verify that wakeLock is acquired in ECM assertEquals(true, mImsPhoneUT.getWakeLock().isHeld()); mImsPhoneUT.setOnEcbModeExitResponse(mTestHandler, EVENT_EMERGENCY_CALLBACK_MODE_EXIT, null); // verify handling of emergency callback mode exit imsEcbmStateListener.onECBMExited(); // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED verify(mIActivityManager, atLeast(2)).broadcastIntent(eq((IApplicationThread)null), intentArgumentCaptor.capture(), eq((String)null), eq((IIntentReceiver)null), eq(Activity.RESULT_OK), eq((String)null), eq((Bundle)null), eq((String[])null), anyInt(), eq((Bundle)null), eq(false), eq(true), anyInt()); intent = intentArgumentCaptor.getValue(); assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction()); assertEquals(false, intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, true)); ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); // verify EcmExitRespRegistrant is notified verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong()); assertEquals(EVENT_EMERGENCY_CALLBACK_MODE_EXIT, messageArgumentCaptor.getValue().what); // verify wakeLock released assertEquals(false, mImsPhoneUT.getWakeLock().isHeld()); } @FlakyTest @Test @SmallTest public void testProcessDisconnectReason() throws Exception { // set up CarrierConfig PersistableBundle bundle = mContextFixture.getCarrierConfigBundle(); bundle.putStringArray(CarrierConfigManager.KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, new String[]{"REG09|0"}); // set up overlays String title = "title"; String messageAlert = "Alert!"; String messageNotification = "Notification!"; mContextFixture.putStringArrayResource( com.android.internal.R.array.wfcOperatorErrorAlertMessages, new String[]{messageAlert}); mContextFixture.putStringArrayResource( com.android.internal.R.array.wfcOperatorErrorNotificationMessages, new String[]{messageNotification}); mContextFixture.putResource(com.android.internal.R.string.wfcRegErrorTitle, title); mImsPhoneUT.processDisconnectReason( new ImsReasonInfo(ImsReasonInfo.CODE_REGISTRATION_ERROR, 0, "REG09")); // TODO: Verify that WFC has been turned off (can't do it right now because // setWfcSetting is static). //verify(mImsManager).setWfcSetting(any(), eq(false)); ArgumentCaptor intent = ArgumentCaptor.forClass(Intent.class); verify(mContext).sendOrderedBroadcast( intent.capture(), nullable(String.class), any(BroadcastReceiver.class), nullable(Handler.class), eq(Activity.RESULT_OK), nullable(String.class), nullable(Bundle.class)); assertEquals(ImsManager.ACTION_IMS_REGISTRATION_ERROR, intent.getValue().getAction()); assertEquals(title, intent.getValue().getStringExtra(Phone.EXTRA_KEY_ALERT_TITLE)); assertEquals(messageAlert, intent.getValue().getStringExtra(Phone.EXTRA_KEY_ALERT_MESSAGE)); assertEquals(messageNotification, intent.getValue().getStringExtra(Phone.EXTRA_KEY_NOTIFICATION_MESSAGE)); } }