Loading src/java/com/android/internal/telephony/CellBroadcastServiceManager.java +44 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import android.telephony.ICellBroadcastService; import android.util.LocalLog; import android.util.Log; import com.android.internal.telephony.cdma.SmsMessage; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -53,7 +55,8 @@ public class CellBroadcastServiceManager { private final LocalLog mLocalLog = new LocalLog(100); /** New SMS cell broadcast received as an AsyncResult. */ private static final int EVENT_NEW_SMS_CB = 0; private static final int EVENT_NEW_GSM_SMS_CB = 0; private static final int EVENT_NEW_CDMA_SMS_CB = 1; private boolean mEnabled; public CellBroadcastServiceManager(Context context, Phone phone) { Loading @@ -63,10 +66,22 @@ public class CellBroadcastServiceManager { } /** * Send a CB message to the CellBroadcastServieManager's handler. * Send a GSM CB message to the CellBroadcastServieManager's handler. * @param m the message */ public void sendMessageToHandler(Message m) { public void sendGsmMessageToHandler(Message m) { m.what = EVENT_NEW_GSM_SMS_CB; mModuleCellBroadcastHandler.sendMessage(m); } /** * Send a CDMA CB message to the CellBroadcastServieManager's handler. * @param sms the SmsMessage to forward */ public void sendCdmaMessageToHandler(SmsMessage sms) { Message m = Message.obtain(); m.what = EVENT_NEW_CDMA_SMS_CB; m.obj = sms; mModuleCellBroadcastHandler.sendMessage(m); } Loading Loading @@ -106,12 +121,25 @@ public class CellBroadcastServiceManager { Log.d(TAG, "CB module is disabled."); return; } if (sServiceConnection.mService == null) { Log.d(TAG, "No connection to CB module, ignoring message."); return; } try { ICellBroadcastService cellBroadcastService = ICellBroadcastService.Stub.asInterface( sServiceConnection.mService); if (msg.what == EVENT_NEW_GSM_SMS_CB) { mLocalLog.log("GSM SMS CB for phone " + mPhone.getPhoneId()); cellBroadcastService.handleGsmCellBroadcastSms(mPhone.getPhoneId(), (byte[]) ((AsyncResult) msg.obj).result); } else if (msg.what == EVENT_NEW_CDMA_SMS_CB) { mLocalLog.log("CDMA SMS CB for phone " + mPhone.getPhoneId()); SmsMessage sms = (SmsMessage) msg.obj; cellBroadcastService.handleCdmaCellBroadcastSms(mPhone.getPhoneId(), sms.getEnvelopeBearerData(), sms.getEnvelopeServiceCategory()); } } catch (RemoteException e) { Log.e(TAG, "Failed to connect to default app: " + mCellBroadcastServicePackage + " err: " + e.toString()); Loading @@ -128,7 +156,7 @@ public class CellBroadcastServiceManager { if (sServiceConnection.mService == null) { mContext.bindService(intent, sServiceConnection, Context.BIND_AUTO_CREATE); } mPhone.mCi.setOnNewGsmBroadcastSms(mModuleCellBroadcastHandler, EVENT_NEW_SMS_CB, mPhone.mCi.setOnNewGsmBroadcastSms(mModuleCellBroadcastHandler, EVENT_NEW_GSM_SMS_CB, null); } else { Log.e(TAG, "Unable to bind service; no cell broadcast service found"); Loading Loading @@ -156,6 +184,16 @@ public class CellBroadcastServiceManager { Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly"); this.mService = null; } @Override public void onBindingDied(ComponentName name) { Log.d(TAG, "Binding died"); } @Override public void onNullBinding(ComponentName name) { Log.d(TAG, "Null binding"); } } /** Loading src/java/com/android/internal/telephony/InboundSmsHandler.java +77 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,10 @@ public abstract class InboundSmsHandler extends StateMachine { @UnsupportedAppUsage IDeviceIdleController mDeviceIdleController; protected static boolean sEnableCbModule = false; protected CellBroadcastServiceManager mCellBroadcastServiceManager; // Delete permanently from raw table private final int DELETE_PERMANENTLY = 1; // Only mark deleted, but keep in db for message de-duping Loading Loading @@ -283,6 +287,7 @@ public abstract class InboundSmsHandler extends StateMachine { mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mDeviceIdleController = TelephonyComponentFactory.getInstance() .inject(IDeviceIdleController.class.getName()).getIDeviceIdleController(); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); addState(mDefaultState); addState(mStartupState, mDefaultState); Loading @@ -307,6 +312,7 @@ public abstract class InboundSmsHandler extends StateMachine { @Override protected void onQuitting() { mWapPush.dispose(); mCellBroadcastServiceManager.disable(); while (mWakeLock.isHeld()) { mWakeLock.release(); Loading Loading @@ -1702,6 +1708,9 @@ public abstract class InboundSmsHandler extends StateMachine { if (mCellBroadcastHandler != null) { mCellBroadcastHandler.dump(fd, pw, args); } if (mCellBroadcastServiceManager != null) { mCellBroadcastServiceManager.dump(fd, pw, args); } mLocalLog.dump(fd, pw, args); } Loading Loading @@ -1746,6 +1755,32 @@ public abstract class InboundSmsHandler extends StateMachine { } } protected byte[] decodeHexString(String hexString) { if (hexString == null || hexString.length() % 2 == 1) { return null; } byte[] bytes = new byte[hexString.length() / 2]; for (int i = 0; i < hexString.length(); i += 2) { bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); } return bytes; } private byte hexToByte(String hexString) { int firstDigit = toDigit(hexString.charAt(0)); int secondDigit = toDigit(hexString.charAt(1)); return (byte) ((firstDigit << 4) + secondDigit); } private int toDigit(char hexChar) { int digit = Character.digit(hexChar, 16); if (digit == -1) { return 0; } return digit; } /** * Registers the broadcast receiver to launch the default SMS app when the user clicks the * new message notification. Loading @@ -1755,4 +1790,46 @@ public abstract class InboundSmsHandler extends StateMachine { userFilter.addAction(ACTION_OPEN_SMS_APP); context.registerReceiver(new NewMessageNotificationActionReceiver(), userFilter); } protected abstract class CbTestBroadcastReceiver extends BroadcastReceiver { protected abstract void handleTestAction(Intent intent); protected abstract void handleToggleEnable(); protected abstract void handleToggleDisable(Context context); protected final String mTestAction; protected final String mToggleAction; public CbTestBroadcastReceiver(String testAction, String toggleAction) { mTestAction = testAction; mToggleAction = toggleAction; } @Override public void onReceive(Context context, Intent intent) { logd("Received test intent action=" + intent.getAction()); if (intent.getAction().equals(mTestAction)) { // Return early if phone_id is explicilty included and does not match mPhone. // If phone_id extra is not included, continue. int phoneId = mPhone.getPhoneId(); if (intent.getIntExtra("phone_id", phoneId) != phoneId) { return; } handleTestAction(intent); } else if (intent.getAction().equals(mToggleAction)) { if (intent.hasExtra("enable")) { sEnableCbModule = intent.getBooleanExtra("enable", false); } else { sEnableCbModule = !sEnableCbModule; } if (sEnableCbModule) { log("enabling CB module"); handleToggleEnable(); } else { log("enabling legacy platform CB handling"); handleToggleDisable(context); } } } } } src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java +111 −6 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.telephony.cdma; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.Message; import android.provider.Telephony.Sms.Intents; Loading @@ -34,6 +36,7 @@ import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.WspTypeDecoder; import com.android.internal.telephony.cdma.sms.CdmaSmsAddress; import com.android.internal.telephony.cdma.sms.SmsEnvelope; import com.android.internal.util.HexDump; Loading @@ -46,6 +49,7 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { private final CdmaSMSDispatcher mSmsDispatcher; private final CdmaServiceCategoryProgramHandler mServiceCategoryProgramHandler; private static CdmaCbTestBroadcastReceiver sTestBroadcastReceiver; private byte[] mLastDispatchedSmsFingerprint; private byte[] mLastAcknowledgedSmsFingerprint; Loading @@ -53,6 +57,15 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { private final boolean mCheckForDuplicatePortsInOmadmWapPush = Resources.getSystem().getBoolean( com.android.internal.R.bool.config_duplicate_port_omadm_wappush); // When TEST_MODE is on we allow the test intent to trigger an SMS CB alert private static boolean sEnableCbModule = false; private static final boolean TEST_MODE = true; //STOPSHIP if true private static final String TEST_ACTION = "com.android.internal.telephony.cdma" + ".TEST_TRIGGER_CELL_BROADCAST"; private static final String TOGGLE_CB_MODULE = "com.android.internal.telephony.cdma" + ".TOGGLE_CB_MODULE"; /** * Create a new inbound SMS handler for CDMA. */ Loading @@ -64,6 +77,17 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context, phone.mCi); phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null); mCellBroadcastServiceManager.enable(); if (TEST_MODE) { if (sTestBroadcastReceiver == null) { sTestBroadcastReceiver = new CdmaCbTestBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(TEST_ACTION); filter.addAction(TOGGLE_CB_MODULE); context.registerReceiver(sTestBroadcastReceiver, filter); } } } /** Loading Loading @@ -111,13 +135,10 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { // Handle CMAS emergency broadcast messages. if (isBroadcastType) { log("Broadcast type message"); String plmn = TelephonyManager.from(mContext).getNetworkOperatorForPhone(mPhone.getPhoneId()); SmsCbMessage cbMessage = sms.parseBroadcastSms(plmn, mPhone.getPhoneId()); if (cbMessage != null) { mCellBroadcastHandler.dispatchSmsMessage(cbMessage); if (sEnableCbModule) { mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms); } else { loge("error trying to parse broadcast SMS"); legacyDispatchSmsCbMessage(sms); } return Intents.RESULT_SMS_HANDLED; } Loading Loading @@ -184,6 +205,19 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { return dispatchNormalMessage(smsb); } // dispatch an SMS message through the platform private void legacyDispatchSmsCbMessage(SmsMessage sms) { String plmn = TelephonyManager.from(mContext).getNetworkOperatorForPhone( mPhone.getPhoneId()); SmsCbMessage cbMessage = sms.parseBroadcastSms(plmn, mPhone.getPhoneId()); if (cbMessage != null) { mCellBroadcastHandler.dispatchSmsMessage(cbMessage); } else { loge("error trying to parse broadcast SMS"); } } /** * Send an acknowledge message. * @param success indicates that last message was successfully received. Loading Loading @@ -349,4 +383,75 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), android.telephony.SmsMessage.FORMAT_3GPP2); } /** * A broadcast receiver used for testing emergency cell broadcasts. To trigger test CDMA cell * broadcasts with adb run e.g: * * adb shell am broadcast -a com.android.internal.telephony.cdma.TEST_TRIGGER_CELL_BROADCAST \ * --ei service_category 4097 \ * --es bearer_data_string 00031303900801C00D0101015C02D00002BFD1931054D208119313D3D10815D05 \ * 493925391C81193D48814D3D555120810D3D0D3D3925393C810D3D5539516480B481393D495120810D1539514 \ * 9053081054925693D390481553951253080D0C4D481413481354D500 * * adb shell am broadcast -a com.android.internal.telephony.cdma.TEST_TRIGGER_CELL_BROADCAST \ * --ei service_category 4097 \ * --es bearer_data_string 00031303900801C00D0101015C02D00002BFD1931054D208119313D3D10815D05 \ * 493925391C81193D48814D3D555120810D3D0D3D3925393C810D3D5539516480B481393D495120810D1539514 \ * 9053081054925693D390481553951253080D0C4D481413481354D500 \ * --ei phone_id 0 \ * * adb shell am broadcast -a com.android.internal.telephony.cdma.TOGGLE_CB_MODULE * * adb shell am broadcast -a com.android.internal.telephony.cdma.TOGGLE_CB_MODULE \ * --ez enable true */ private class CdmaCbTestBroadcastReceiver extends CbTestBroadcastReceiver { CdmaCbTestBroadcastReceiver() { super(TEST_ACTION, TOGGLE_CB_MODULE); } @Override protected void handleTestAction(Intent intent) { SmsEnvelope envelope = new SmsEnvelope(); // the CdmaSmsAddress is not used for a test cell broadcast message, but needs to be // supplied to avoid a null pointer exception in the platform CdmaSmsAddress nonNullAddress = new CdmaSmsAddress(); nonNullAddress.origBytes = new byte[] { (byte) 0xFF }; envelope.origAddress = nonNullAddress; // parse service category from intent envelope.serviceCategory = intent.getIntExtra("service_category", -1); if (envelope.serviceCategory == -1) { log("No service category, ignoring CB test intent"); return; } // parse bearer data from intent String bearerDataString = intent.getStringExtra("bearer_data_string"); envelope.bearerData = decodeHexString(bearerDataString); if (envelope.bearerData == null) { log("No bearer data, ignoring CB test intent"); return; } SmsMessage sms = new SmsMessage(new CdmaSmsAddress(), envelope); if (sEnableCbModule) { mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms); } else { legacyDispatchSmsCbMessage(sms); } } @Override protected void handleToggleEnable() { // sEnableCbModule is already toggled in super class } @Override protected void handleToggleDisable(Context context) { // sEnableCbModule is already toggled in super class } } } src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java +52 −91 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import android.os.AsyncResult; import android.os.Message; import android.provider.Telephony.Sms.Intents; import com.android.internal.telephony.CellBroadcastServiceManager; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.InboundSmsHandler; import com.android.internal.telephony.Phone; Loading @@ -36,9 +35,6 @@ import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.VisualVoicemailSmsFilter; import com.android.internal.telephony.uicc.UsimServiceTable; import java.io.FileDescriptor; import java.io.PrintWriter; /** * This class broadcasts incoming SMS messages to interested apps after storing them in * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been Loading @@ -50,13 +46,11 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { private final UsimDataDownloadHandler mDataDownloadHandler; // When TEST_MODE is on we allow the test intent to trigger an SMS CB alert private static boolean sEnableCbModule = false; private static final boolean TEST_MODE = true; //STOPSHIP if true private static final String TEST_ACTION = "com.android.internal.telephony.gsm" + ".TEST_TRIGGER_CELL_BROADCAST"; private static final String TOGGLE_CB_MODULE = "com.android.internal.telephony.gsm" + ".TOGGLE_CB_MODULE"; private CellBroadcastServiceManager mCellBroadcastServiceManager; /** * Create a new GSM inbound SMS handler. Loading @@ -66,7 +60,6 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { super("GsmInboundSmsHandler", context, storageMonitor, phone, null); phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId()); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); if (sEnableCbModule) { mCellBroadcastServiceManager.enable(); } else { Loading @@ -75,6 +68,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { } if (TEST_MODE) { if (sTestBroadcastReceiver == null) { sTestBroadcastReceiver = new GsmCbTestBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(TEST_ACTION); Loading @@ -82,6 +76,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { context.registerReceiver(sTestBroadcastReceiver, filter); } } } /** Loading @@ -100,13 +95,17 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { * * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE * * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE -ez enable true * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE \ * --ez enable true */ private class GsmCbTestBroadcastReceiver extends BroadcastReceiver { private class GsmCbTestBroadcastReceiver extends CbTestBroadcastReceiver { GsmCbTestBroadcastReceiver() { super(TEST_ACTION, TOGGLE_CB_MODULE); } @Override public void onReceive(Context context, Intent intent) { logd("Received test intent action=" + intent.getAction()); if (intent.getAction() == TEST_ACTION) { protected void handleTestAction(Intent intent) { byte[] smsPdu = intent.getByteArrayExtra("pdu"); if (smsPdu == null) { String pduString = intent.getStringExtra("pdu_string"); Loading @@ -126,23 +125,21 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { Message m = Message.obtain(); AsyncResult.forMessage(m, smsPdu, null); if (sEnableCbModule) { mCellBroadcastServiceManager.sendMessageToHandler(m); mCellBroadcastServiceManager.sendGsmMessageToHandler(m); } else { m.setWhat(GsmCellBroadcastHandler.EVENT_NEW_SMS_MESSAGE); mCellBroadcastHandler.sendMessage(m); } } else if (intent.getAction() == TOGGLE_CB_MODULE) { if (intent.hasExtra("enable")) { sEnableCbModule = intent.getBooleanExtra("enable", false); } else { sEnableCbModule = !sEnableCbModule; } if (sEnableCbModule) { log("enabling CB module"); @Override protected void handleToggleEnable() { mPhone.mCi.unSetOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler()); mCellBroadcastServiceManager.enable(); } else { log("enabling legacy platform CB handling"); } @Override protected void handleToggleDisable(Context context) { mCellBroadcastServiceManager.disable(); if (mCellBroadcastHandler == null) { mCellBroadcastHandler = Loading @@ -153,33 +150,6 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { GsmCellBroadcastHandler.EVENT_NEW_SMS_MESSAGE, null); } } } } private byte[] decodeHexString(String hexString) { if (hexString == null || hexString.length() % 2 == 1) { return null; } byte[] bytes = new byte[hexString.length() / 2]; for (int i = 0; i < hexString.length(); i += 2) { bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); } return bytes; } private byte hexToByte(String hexString) { int firstDigit = toDigit(hexString.charAt(0)); int secondDigit = toDigit(hexString.charAt(1)); return (byte) ((firstDigit << 4) + secondDigit); } private int toDigit(char hexChar) { int digit = Character.digit(hexChar, 16); if (digit == -1) { return 0; } return digit; } /** * Unregister for GSM SMS. Loading @@ -187,7 +157,6 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { @Override protected void onQuitting() { mPhone.mCi.unSetOnNewGsmSms(getHandler()); mCellBroadcastServiceManager.disable(); mCellBroadcastHandler.dispose(); if (DBG) log("unregistered for 3GPP SMS"); Loading Loading @@ -335,12 +304,4 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), android.telephony.SmsMessage.FORMAT_3GPP); } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { super.dump(fd, pw, args); if (mCellBroadcastServiceManager != null) { mCellBroadcastServiceManager.dump(fd, pw, args); } } } tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -807,7 +807,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest { // verify that a broadcast receiver is registered for current user (user == null) based on // implementation in ContextFixture verify(mContext, times(2)).registerReceiverAsUser(any(BroadcastReceiver.class), verify(mContext, times(1)).registerReceiverAsUser(any(BroadcastReceiver.class), eq((UserHandle)null), any(IntentFilter.class), eq((String)null), eq((Handler)null)); // wait for ScanRawTableThread Loading Loading
src/java/com/android/internal/telephony/CellBroadcastServiceManager.java +44 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ import android.telephony.ICellBroadcastService; import android.util.LocalLog; import android.util.Log; import com.android.internal.telephony.cdma.SmsMessage; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -53,7 +55,8 @@ public class CellBroadcastServiceManager { private final LocalLog mLocalLog = new LocalLog(100); /** New SMS cell broadcast received as an AsyncResult. */ private static final int EVENT_NEW_SMS_CB = 0; private static final int EVENT_NEW_GSM_SMS_CB = 0; private static final int EVENT_NEW_CDMA_SMS_CB = 1; private boolean mEnabled; public CellBroadcastServiceManager(Context context, Phone phone) { Loading @@ -63,10 +66,22 @@ public class CellBroadcastServiceManager { } /** * Send a CB message to the CellBroadcastServieManager's handler. * Send a GSM CB message to the CellBroadcastServieManager's handler. * @param m the message */ public void sendMessageToHandler(Message m) { public void sendGsmMessageToHandler(Message m) { m.what = EVENT_NEW_GSM_SMS_CB; mModuleCellBroadcastHandler.sendMessage(m); } /** * Send a CDMA CB message to the CellBroadcastServieManager's handler. * @param sms the SmsMessage to forward */ public void sendCdmaMessageToHandler(SmsMessage sms) { Message m = Message.obtain(); m.what = EVENT_NEW_CDMA_SMS_CB; m.obj = sms; mModuleCellBroadcastHandler.sendMessage(m); } Loading Loading @@ -106,12 +121,25 @@ public class CellBroadcastServiceManager { Log.d(TAG, "CB module is disabled."); return; } if (sServiceConnection.mService == null) { Log.d(TAG, "No connection to CB module, ignoring message."); return; } try { ICellBroadcastService cellBroadcastService = ICellBroadcastService.Stub.asInterface( sServiceConnection.mService); if (msg.what == EVENT_NEW_GSM_SMS_CB) { mLocalLog.log("GSM SMS CB for phone " + mPhone.getPhoneId()); cellBroadcastService.handleGsmCellBroadcastSms(mPhone.getPhoneId(), (byte[]) ((AsyncResult) msg.obj).result); } else if (msg.what == EVENT_NEW_CDMA_SMS_CB) { mLocalLog.log("CDMA SMS CB for phone " + mPhone.getPhoneId()); SmsMessage sms = (SmsMessage) msg.obj; cellBroadcastService.handleCdmaCellBroadcastSms(mPhone.getPhoneId(), sms.getEnvelopeBearerData(), sms.getEnvelopeServiceCategory()); } } catch (RemoteException e) { Log.e(TAG, "Failed to connect to default app: " + mCellBroadcastServicePackage + " err: " + e.toString()); Loading @@ -128,7 +156,7 @@ public class CellBroadcastServiceManager { if (sServiceConnection.mService == null) { mContext.bindService(intent, sServiceConnection, Context.BIND_AUTO_CREATE); } mPhone.mCi.setOnNewGsmBroadcastSms(mModuleCellBroadcastHandler, EVENT_NEW_SMS_CB, mPhone.mCi.setOnNewGsmBroadcastSms(mModuleCellBroadcastHandler, EVENT_NEW_GSM_SMS_CB, null); } else { Log.e(TAG, "Unable to bind service; no cell broadcast service found"); Loading Loading @@ -156,6 +184,16 @@ public class CellBroadcastServiceManager { Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly"); this.mService = null; } @Override public void onBindingDied(ComponentName name) { Log.d(TAG, "Binding died"); } @Override public void onNullBinding(ComponentName name) { Log.d(TAG, "Null binding"); } } /** Loading
src/java/com/android/internal/telephony/InboundSmsHandler.java +77 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,10 @@ public abstract class InboundSmsHandler extends StateMachine { @UnsupportedAppUsage IDeviceIdleController mDeviceIdleController; protected static boolean sEnableCbModule = false; protected CellBroadcastServiceManager mCellBroadcastServiceManager; // Delete permanently from raw table private final int DELETE_PERMANENTLY = 1; // Only mark deleted, but keep in db for message de-duping Loading Loading @@ -283,6 +287,7 @@ public abstract class InboundSmsHandler extends StateMachine { mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mDeviceIdleController = TelephonyComponentFactory.getInstance() .inject(IDeviceIdleController.class.getName()).getIDeviceIdleController(); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); addState(mDefaultState); addState(mStartupState, mDefaultState); Loading @@ -307,6 +312,7 @@ public abstract class InboundSmsHandler extends StateMachine { @Override protected void onQuitting() { mWapPush.dispose(); mCellBroadcastServiceManager.disable(); while (mWakeLock.isHeld()) { mWakeLock.release(); Loading Loading @@ -1702,6 +1708,9 @@ public abstract class InboundSmsHandler extends StateMachine { if (mCellBroadcastHandler != null) { mCellBroadcastHandler.dump(fd, pw, args); } if (mCellBroadcastServiceManager != null) { mCellBroadcastServiceManager.dump(fd, pw, args); } mLocalLog.dump(fd, pw, args); } Loading Loading @@ -1746,6 +1755,32 @@ public abstract class InboundSmsHandler extends StateMachine { } } protected byte[] decodeHexString(String hexString) { if (hexString == null || hexString.length() % 2 == 1) { return null; } byte[] bytes = new byte[hexString.length() / 2]; for (int i = 0; i < hexString.length(); i += 2) { bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); } return bytes; } private byte hexToByte(String hexString) { int firstDigit = toDigit(hexString.charAt(0)); int secondDigit = toDigit(hexString.charAt(1)); return (byte) ((firstDigit << 4) + secondDigit); } private int toDigit(char hexChar) { int digit = Character.digit(hexChar, 16); if (digit == -1) { return 0; } return digit; } /** * Registers the broadcast receiver to launch the default SMS app when the user clicks the * new message notification. Loading @@ -1755,4 +1790,46 @@ public abstract class InboundSmsHandler extends StateMachine { userFilter.addAction(ACTION_OPEN_SMS_APP); context.registerReceiver(new NewMessageNotificationActionReceiver(), userFilter); } protected abstract class CbTestBroadcastReceiver extends BroadcastReceiver { protected abstract void handleTestAction(Intent intent); protected abstract void handleToggleEnable(); protected abstract void handleToggleDisable(Context context); protected final String mTestAction; protected final String mToggleAction; public CbTestBroadcastReceiver(String testAction, String toggleAction) { mTestAction = testAction; mToggleAction = toggleAction; } @Override public void onReceive(Context context, Intent intent) { logd("Received test intent action=" + intent.getAction()); if (intent.getAction().equals(mTestAction)) { // Return early if phone_id is explicilty included and does not match mPhone. // If phone_id extra is not included, continue. int phoneId = mPhone.getPhoneId(); if (intent.getIntExtra("phone_id", phoneId) != phoneId) { return; } handleTestAction(intent); } else if (intent.getAction().equals(mToggleAction)) { if (intent.hasExtra("enable")) { sEnableCbModule = intent.getBooleanExtra("enable", false); } else { sEnableCbModule = !sEnableCbModule; } if (sEnableCbModule) { log("enabling CB module"); handleToggleEnable(); } else { log("enabling legacy platform CB handling"); handleToggleDisable(context); } } } } }
src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java +111 −6 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.telephony.cdma; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.Message; import android.provider.Telephony.Sms.Intents; Loading @@ -34,6 +36,7 @@ import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.WspTypeDecoder; import com.android.internal.telephony.cdma.sms.CdmaSmsAddress; import com.android.internal.telephony.cdma.sms.SmsEnvelope; import com.android.internal.util.HexDump; Loading @@ -46,6 +49,7 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { private final CdmaSMSDispatcher mSmsDispatcher; private final CdmaServiceCategoryProgramHandler mServiceCategoryProgramHandler; private static CdmaCbTestBroadcastReceiver sTestBroadcastReceiver; private byte[] mLastDispatchedSmsFingerprint; private byte[] mLastAcknowledgedSmsFingerprint; Loading @@ -53,6 +57,15 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { private final boolean mCheckForDuplicatePortsInOmadmWapPush = Resources.getSystem().getBoolean( com.android.internal.R.bool.config_duplicate_port_omadm_wappush); // When TEST_MODE is on we allow the test intent to trigger an SMS CB alert private static boolean sEnableCbModule = false; private static final boolean TEST_MODE = true; //STOPSHIP if true private static final String TEST_ACTION = "com.android.internal.telephony.cdma" + ".TEST_TRIGGER_CELL_BROADCAST"; private static final String TOGGLE_CB_MODULE = "com.android.internal.telephony.cdma" + ".TOGGLE_CB_MODULE"; /** * Create a new inbound SMS handler for CDMA. */ Loading @@ -64,6 +77,17 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context, phone.mCi); phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null); mCellBroadcastServiceManager.enable(); if (TEST_MODE) { if (sTestBroadcastReceiver == null) { sTestBroadcastReceiver = new CdmaCbTestBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(TEST_ACTION); filter.addAction(TOGGLE_CB_MODULE); context.registerReceiver(sTestBroadcastReceiver, filter); } } } /** Loading Loading @@ -111,13 +135,10 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { // Handle CMAS emergency broadcast messages. if (isBroadcastType) { log("Broadcast type message"); String plmn = TelephonyManager.from(mContext).getNetworkOperatorForPhone(mPhone.getPhoneId()); SmsCbMessage cbMessage = sms.parseBroadcastSms(plmn, mPhone.getPhoneId()); if (cbMessage != null) { mCellBroadcastHandler.dispatchSmsMessage(cbMessage); if (sEnableCbModule) { mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms); } else { loge("error trying to parse broadcast SMS"); legacyDispatchSmsCbMessage(sms); } return Intents.RESULT_SMS_HANDLED; } Loading Loading @@ -184,6 +205,19 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { return dispatchNormalMessage(smsb); } // dispatch an SMS message through the platform private void legacyDispatchSmsCbMessage(SmsMessage sms) { String plmn = TelephonyManager.from(mContext).getNetworkOperatorForPhone( mPhone.getPhoneId()); SmsCbMessage cbMessage = sms.parseBroadcastSms(plmn, mPhone.getPhoneId()); if (cbMessage != null) { mCellBroadcastHandler.dispatchSmsMessage(cbMessage); } else { loge("error trying to parse broadcast SMS"); } } /** * Send an acknowledge message. * @param success indicates that last message was successfully received. Loading Loading @@ -349,4 +383,75 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler { mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), android.telephony.SmsMessage.FORMAT_3GPP2); } /** * A broadcast receiver used for testing emergency cell broadcasts. To trigger test CDMA cell * broadcasts with adb run e.g: * * adb shell am broadcast -a com.android.internal.telephony.cdma.TEST_TRIGGER_CELL_BROADCAST \ * --ei service_category 4097 \ * --es bearer_data_string 00031303900801C00D0101015C02D00002BFD1931054D208119313D3D10815D05 \ * 493925391C81193D48814D3D555120810D3D0D3D3925393C810D3D5539516480B481393D495120810D1539514 \ * 9053081054925693D390481553951253080D0C4D481413481354D500 * * adb shell am broadcast -a com.android.internal.telephony.cdma.TEST_TRIGGER_CELL_BROADCAST \ * --ei service_category 4097 \ * --es bearer_data_string 00031303900801C00D0101015C02D00002BFD1931054D208119313D3D10815D05 \ * 493925391C81193D48814D3D555120810D3D0D3D3925393C810D3D5539516480B481393D495120810D1539514 \ * 9053081054925693D390481553951253080D0C4D481413481354D500 \ * --ei phone_id 0 \ * * adb shell am broadcast -a com.android.internal.telephony.cdma.TOGGLE_CB_MODULE * * adb shell am broadcast -a com.android.internal.telephony.cdma.TOGGLE_CB_MODULE \ * --ez enable true */ private class CdmaCbTestBroadcastReceiver extends CbTestBroadcastReceiver { CdmaCbTestBroadcastReceiver() { super(TEST_ACTION, TOGGLE_CB_MODULE); } @Override protected void handleTestAction(Intent intent) { SmsEnvelope envelope = new SmsEnvelope(); // the CdmaSmsAddress is not used for a test cell broadcast message, but needs to be // supplied to avoid a null pointer exception in the platform CdmaSmsAddress nonNullAddress = new CdmaSmsAddress(); nonNullAddress.origBytes = new byte[] { (byte) 0xFF }; envelope.origAddress = nonNullAddress; // parse service category from intent envelope.serviceCategory = intent.getIntExtra("service_category", -1); if (envelope.serviceCategory == -1) { log("No service category, ignoring CB test intent"); return; } // parse bearer data from intent String bearerDataString = intent.getStringExtra("bearer_data_string"); envelope.bearerData = decodeHexString(bearerDataString); if (envelope.bearerData == null) { log("No bearer data, ignoring CB test intent"); return; } SmsMessage sms = new SmsMessage(new CdmaSmsAddress(), envelope); if (sEnableCbModule) { mCellBroadcastServiceManager.sendCdmaMessageToHandler(sms); } else { legacyDispatchSmsCbMessage(sms); } } @Override protected void handleToggleEnable() { // sEnableCbModule is already toggled in super class } @Override protected void handleToggleDisable(Context context) { // sEnableCbModule is already toggled in super class } } }
src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java +52 −91 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import android.os.AsyncResult; import android.os.Message; import android.provider.Telephony.Sms.Intents; import com.android.internal.telephony.CellBroadcastServiceManager; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.InboundSmsHandler; import com.android.internal.telephony.Phone; Loading @@ -36,9 +35,6 @@ import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.VisualVoicemailSmsFilter; import com.android.internal.telephony.uicc.UsimServiceTable; import java.io.FileDescriptor; import java.io.PrintWriter; /** * This class broadcasts incoming SMS messages to interested apps after storing them in * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been Loading @@ -50,13 +46,11 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { private final UsimDataDownloadHandler mDataDownloadHandler; // When TEST_MODE is on we allow the test intent to trigger an SMS CB alert private static boolean sEnableCbModule = false; private static final boolean TEST_MODE = true; //STOPSHIP if true private static final String TEST_ACTION = "com.android.internal.telephony.gsm" + ".TEST_TRIGGER_CELL_BROADCAST"; private static final String TOGGLE_CB_MODULE = "com.android.internal.telephony.gsm" + ".TOGGLE_CB_MODULE"; private CellBroadcastServiceManager mCellBroadcastServiceManager; /** * Create a new GSM inbound SMS handler. Loading @@ -66,7 +60,6 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { super("GsmInboundSmsHandler", context, storageMonitor, phone, null); phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId()); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); if (sEnableCbModule) { mCellBroadcastServiceManager.enable(); } else { Loading @@ -75,6 +68,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { } if (TEST_MODE) { if (sTestBroadcastReceiver == null) { sTestBroadcastReceiver = new GsmCbTestBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(TEST_ACTION); Loading @@ -82,6 +76,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { context.registerReceiver(sTestBroadcastReceiver, filter); } } } /** Loading @@ -100,13 +95,17 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { * * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE * * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE -ez enable true * adb shell am broadcast -a com.android.internal.telephony.gsm.TOGGLE_CB_MODULE \ * --ez enable true */ private class GsmCbTestBroadcastReceiver extends BroadcastReceiver { private class GsmCbTestBroadcastReceiver extends CbTestBroadcastReceiver { GsmCbTestBroadcastReceiver() { super(TEST_ACTION, TOGGLE_CB_MODULE); } @Override public void onReceive(Context context, Intent intent) { logd("Received test intent action=" + intent.getAction()); if (intent.getAction() == TEST_ACTION) { protected void handleTestAction(Intent intent) { byte[] smsPdu = intent.getByteArrayExtra("pdu"); if (smsPdu == null) { String pduString = intent.getStringExtra("pdu_string"); Loading @@ -126,23 +125,21 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { Message m = Message.obtain(); AsyncResult.forMessage(m, smsPdu, null); if (sEnableCbModule) { mCellBroadcastServiceManager.sendMessageToHandler(m); mCellBroadcastServiceManager.sendGsmMessageToHandler(m); } else { m.setWhat(GsmCellBroadcastHandler.EVENT_NEW_SMS_MESSAGE); mCellBroadcastHandler.sendMessage(m); } } else if (intent.getAction() == TOGGLE_CB_MODULE) { if (intent.hasExtra("enable")) { sEnableCbModule = intent.getBooleanExtra("enable", false); } else { sEnableCbModule = !sEnableCbModule; } if (sEnableCbModule) { log("enabling CB module"); @Override protected void handleToggleEnable() { mPhone.mCi.unSetOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler()); mCellBroadcastServiceManager.enable(); } else { log("enabling legacy platform CB handling"); } @Override protected void handleToggleDisable(Context context) { mCellBroadcastServiceManager.disable(); if (mCellBroadcastHandler == null) { mCellBroadcastHandler = Loading @@ -153,33 +150,6 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { GsmCellBroadcastHandler.EVENT_NEW_SMS_MESSAGE, null); } } } } private byte[] decodeHexString(String hexString) { if (hexString == null || hexString.length() % 2 == 1) { return null; } byte[] bytes = new byte[hexString.length() / 2]; for (int i = 0; i < hexString.length(); i += 2) { bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); } return bytes; } private byte hexToByte(String hexString) { int firstDigit = toDigit(hexString.charAt(0)); int secondDigit = toDigit(hexString.charAt(1)); return (byte) ((firstDigit << 4) + secondDigit); } private int toDigit(char hexChar) { int digit = Character.digit(hexChar, 16); if (digit == -1) { return 0; } return digit; } /** * Unregister for GSM SMS. Loading @@ -187,7 +157,6 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { @Override protected void onQuitting() { mPhone.mCi.unSetOnNewGsmSms(getHandler()); mCellBroadcastServiceManager.disable(); mCellBroadcastHandler.dispose(); if (DBG) log("unregistered for 3GPP SMS"); Loading Loading @@ -335,12 +304,4 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), android.telephony.SmsMessage.FORMAT_3GPP); } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { super.dump(fd, pw, args); if (mCellBroadcastServiceManager != null) { mCellBroadcastServiceManager.dump(fd, pw, args); } } }
tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -807,7 +807,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest { // verify that a broadcast receiver is registered for current user (user == null) based on // implementation in ContextFixture verify(mContext, times(2)).registerReceiverAsUser(any(BroadcastReceiver.class), verify(mContext, times(1)).registerReceiverAsUser(any(BroadcastReceiver.class), eq((UserHandle)null), any(IntentFilter.class), eq((String)null), eq((Handler)null)); // wait for ScanRawTableThread Loading