Loading src/java/com/android/internal/telephony/CellBroadcastServiceManager.java 0 → 100644 +171 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2019 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; import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.AsyncResult; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.telephony.CellBroadcastService; import android.telephony.ICellBroadcastService; import android.util.LocalLog; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; /** * Manages a single binding to the CellBroadcastService from the platform. In mSIM cases callers * should have one CellBroadcastServiceManager per phone, and the CellBroadcastServiceManager * will handle the single binding. */ public class CellBroadcastServiceManager { private static final String TAG = "CellBroadcastServiceManager"; private String mCellBroadcastServicePackage; private static CellBroadcastServiceConnection sServiceConnection; private Handler mModuleCellBroadcastHandler = null; private Phone mPhone; private Context mContext; 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 boolean mEnabled; public CellBroadcastServiceManager(Context context, Phone phone) { Log.d(TAG, "CellBroadcastServiceManager created for phone " + phone.getPhoneId()); mContext = context; mPhone = phone; } /** * Send a CB message to the CellBroadcastServieManager's handler. * @param m the message */ public void sendMessageToHandler(Message m) { mModuleCellBroadcastHandler.sendMessage(m); } /** * Enable the CB module. The CellBroadcastService will be bound to and CB messages from the * RIL will be forwarded to the module. */ public void enable() { initCellBroadcastServiceModule(); } /** * Disable the CB module. The manager's handler will no longer receive CB messages from the RIL. */ public void disable() { mEnabled = false; mPhone.mCi.unSetOnNewGsmBroadcastSms(mModuleCellBroadcastHandler); mContext.unbindService(sServiceConnection); } /** * The CellBroadcastServiceManager binds to an implementation of the CellBroadcastService * specified in com.android.internal.R.string.cellbroadcast_default_package (typically the * DefaultCellBroadcastService) and forwards cell broadcast messages to the service. */ private void initCellBroadcastServiceModule() { mEnabled = true; if (sServiceConnection == null) { sServiceConnection = new CellBroadcastServiceConnection(); } mCellBroadcastServicePackage = getCellBroadcastServicePackage(); if (mCellBroadcastServicePackage != null) { mModuleCellBroadcastHandler = new Handler() { @Override public void handleMessage(@NonNull Message msg) { if (!mEnabled) { Log.d(TAG, "CB module is disabled."); return; } try { ICellBroadcastService cellBroadcastService = ICellBroadcastService.Stub.asInterface( sServiceConnection.mService); cellBroadcastService.handleGsmCellBroadcastSms(mPhone.getPhoneId(), (byte[]) ((AsyncResult) msg.obj).result); } catch (RemoteException e) { Log.e(TAG, "Failed to connect to default app: " + mCellBroadcastServicePackage + " err: " + e.toString()); mLocalLog.log("Failed to connect to default app: " + mCellBroadcastServicePackage + " err: " + e.toString()); mContext.unbindService(sServiceConnection); sServiceConnection = null; } } }; Intent intent = new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE); intent.setPackage(mCellBroadcastServicePackage); if (sServiceConnection.mService == null) { mContext.bindService(intent, sServiceConnection, Context.BIND_AUTO_CREATE); } mPhone.mCi.setOnNewGsmBroadcastSms(mModuleCellBroadcastHandler, EVENT_NEW_SMS_CB, null); } else { Log.e(TAG, "Unable to bind service; no cell broadcast service found"); mLocalLog.log("Unable to bind service; no cell broadcast service found"); } } /** Returns the package name of the cell broadcast service, or null if there is none. */ private String getCellBroadcastServicePackage() { return mContext.getResources().getString( com.android.internal.R.string.cellbroadcast_default_package); } private class CellBroadcastServiceConnection implements ServiceConnection { IBinder mService; @Override public void onServiceConnected(ComponentName className, IBinder service) { Log.d(TAG, "connected to CellBroadcastService"); this.mService = service; } @Override public void onServiceDisconnected(ComponentName arg0) { Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly"); this.mService = null; } } /** * Triggered with `adb shell dumpsys isms` */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("CellBroadcastServiceManager:"); pw.println(" mEnabled=" + mEnabled); pw.println(" mCellBroadcastServicePackage=" + mCellBroadcastServicePackage); mLocalLog.dump(fd, pw, args); pw.flush(); } } src/java/com/android/internal/telephony/InboundSmsHandler.java +0 −1 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.IPackageManager; import android.content.pm.UserInfo; import android.database.Cursor; import android.database.Cursor; import android.database.SQLException; import android.database.SQLException; import android.net.Uri; import android.net.Uri; Loading src/java/com/android/internal/telephony/SmsController.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -551,6 +551,9 @@ public class SmsController extends ISmsImplBase { } } } } /** * Triggered by `adb shell dumpsys isms` */ @Override @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!checkDumpPermission(mContext, LOG_TAG, pw)) { if (!checkDumpPermission(mContext, LOG_TAG, pw)) { Loading src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java +145 −3 Original line number Original line Diff line number Diff line Loading @@ -17,10 +17,15 @@ package com.android.internal.telephony.gsm; package com.android.internal.telephony.gsm; import android.app.Activity; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncResult; import android.os.Message; import android.os.Message; import android.provider.Telephony.Sms.Intents; import android.provider.Telephony.Sms.Intents; import com.android.internal.telephony.CellBroadcastServiceManager; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.InboundSmsHandler; import com.android.internal.telephony.InboundSmsHandler; import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone; Loading @@ -31,24 +36,149 @@ import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.VisualVoicemailSmsFilter; import com.android.internal.telephony.VisualVoicemailSmsFilter; import com.android.internal.telephony.uicc.UsimServiceTable; 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 * 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 * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been */ */ public class GsmInboundSmsHandler extends InboundSmsHandler { public class GsmInboundSmsHandler extends InboundSmsHandler { private static BroadcastReceiver sTestBroadcastReceiver; /** Handler for SMS-PP data download messages to UICC. */ /** Handler for SMS-PP data download messages to UICC. */ private final UsimDataDownloadHandler mDataDownloadHandler; 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. * Create a new GSM inbound SMS handler. */ */ private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor, private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor, Phone phone) { Phone phone) { super("GsmInboundSmsHandler", context, storageMonitor, phone, super("GsmInboundSmsHandler", context, storageMonitor, phone, null); GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone)); phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId()); mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId()); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); if (sEnableCbModule) { mCellBroadcastServiceManager.enable(); } else { mCellBroadcastHandler = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone); } if (TEST_MODE) { sTestBroadcastReceiver = new GsmCbTestBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(TEST_ACTION); filter.addAction(TOGGLE_CB_MODULE); context.registerReceiver(sTestBroadcastReceiver, filter); } } /** * A broadcast receiver used for testing emergency cell broadcasts. To trigger test GSM cell * broadcasts with adb run e.g: * * adb shell am broadcast -a com.android.internal.telephony.gsm.TEST_TRIGGER_CELL_BROADCAST \ * --es pdu_string 0000110011010D0A5BAE57CE770C531790E85C716CBF3044573065B9306757309707767 \ * A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09000000000000000 \ * 0000000000000 * * adb shell am broadcast -a com.android.internal.telephony.gsm.TEST_TRIGGER_CELL_BROADCAST \ * --es pdu_string 0000110011010D0A5BAE57CE770C531790E85C716CBF3044573065B9306757309707767 \ * A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09000000000000000 \ * 0000000000000 --ei phone_id 0 * * 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 */ private class GsmCbTestBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { logd("Received test intent action=" + intent.getAction()); if (intent.getAction() == TEST_ACTION) { byte[] smsPdu = intent.getByteArrayExtra("pdu"); if (smsPdu == null) { String pduString = intent.getStringExtra("pdu_string"); smsPdu = decodeHexString(pduString); } if (smsPdu == null) { log("No pdu or pdu_string extra, ignoring CB test intent"); return; } // 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; } Message m = Message.obtain(); AsyncResult.forMessage(m, smsPdu, null); if (sEnableCbModule) { mCellBroadcastServiceManager.sendMessageToHandler(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"); mPhone.mCi.unSetOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler()); mCellBroadcastServiceManager.enable(); } else { log("enabling legacy platform CB handling"); mCellBroadcastServiceManager.disable(); if (mCellBroadcastHandler == null) { mCellBroadcastHandler = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, mPhone); } mPhone.mCi.setOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler(), 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; } } /** /** Loading @@ -57,6 +187,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { @Override @Override protected void onQuitting() { protected void onQuitting() { mPhone.mCi.unSetOnNewGsmSms(getHandler()); mPhone.mCi.unSetOnNewGsmSms(getHandler()); mCellBroadcastServiceManager.disable(); mCellBroadcastHandler.dispose(); mCellBroadcastHandler.dispose(); if (DBG) log("unregistered for 3GPP SMS"); if (DBG) log("unregistered for 3GPP SMS"); Loading @@ -75,6 +206,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { /** /** * Return true if this handler is for 3GPP2 messages; false for 3GPP format. * Return true if this handler is for 3GPP2 messages; false for 3GPP format. * * @return false (3GPP) * @return false (3GPP) */ */ @Override @Override Loading Loading @@ -158,6 +290,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { /** /** * Send an acknowledge message. * Send an acknowledge message. * * @param success indicates that last message was successfully received. * @param success indicates that last message was successfully received. * @param result result code indicating any error * @param result result code indicating any error * @param response callback message sent when operation completes. * @param response callback message sent when operation completes. Loading @@ -169,6 +302,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { /** /** * Convert Android result code to 3GPP SMS failure cause. * Convert Android result code to 3GPP SMS failure cause. * * @param rc the Android SMS intent result value * @param rc the Android SMS intent result value * @return 0 for success, or a 3GPP SMS failure cause value * @return 0 for success, or a 3GPP SMS failure cause value */ */ Loading Loading @@ -201,4 +335,12 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), android.telephony.SmsMessage.FORMAT_3GPP); 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 +2 −2 Original line number Original line Diff line number Diff line Loading @@ -770,8 +770,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest { // verify that a broadcast receiver is registered for current user (user == null) based on // verify that a broadcast receiver is registered for current user (user == null) based on // implementation in ContextFixture // implementation in ContextFixture verify(mContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq((UserHandle)null), verify(mContext, times(2)).registerReceiverAsUser(any(BroadcastReceiver.class), any(IntentFilter.class), eq((String)null), eq((Handler)null)); eq((UserHandle)null), any(IntentFilter.class), eq((String)null), eq((Handler)null)); // wait for ScanRawTableThread // wait for ScanRawTableThread waitForMs(100); waitForMs(100); Loading Loading
src/java/com/android/internal/telephony/CellBroadcastServiceManager.java 0 → 100644 +171 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2019 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; import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.AsyncResult; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.telephony.CellBroadcastService; import android.telephony.ICellBroadcastService; import android.util.LocalLog; import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; /** * Manages a single binding to the CellBroadcastService from the platform. In mSIM cases callers * should have one CellBroadcastServiceManager per phone, and the CellBroadcastServiceManager * will handle the single binding. */ public class CellBroadcastServiceManager { private static final String TAG = "CellBroadcastServiceManager"; private String mCellBroadcastServicePackage; private static CellBroadcastServiceConnection sServiceConnection; private Handler mModuleCellBroadcastHandler = null; private Phone mPhone; private Context mContext; 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 boolean mEnabled; public CellBroadcastServiceManager(Context context, Phone phone) { Log.d(TAG, "CellBroadcastServiceManager created for phone " + phone.getPhoneId()); mContext = context; mPhone = phone; } /** * Send a CB message to the CellBroadcastServieManager's handler. * @param m the message */ public void sendMessageToHandler(Message m) { mModuleCellBroadcastHandler.sendMessage(m); } /** * Enable the CB module. The CellBroadcastService will be bound to and CB messages from the * RIL will be forwarded to the module. */ public void enable() { initCellBroadcastServiceModule(); } /** * Disable the CB module. The manager's handler will no longer receive CB messages from the RIL. */ public void disable() { mEnabled = false; mPhone.mCi.unSetOnNewGsmBroadcastSms(mModuleCellBroadcastHandler); mContext.unbindService(sServiceConnection); } /** * The CellBroadcastServiceManager binds to an implementation of the CellBroadcastService * specified in com.android.internal.R.string.cellbroadcast_default_package (typically the * DefaultCellBroadcastService) and forwards cell broadcast messages to the service. */ private void initCellBroadcastServiceModule() { mEnabled = true; if (sServiceConnection == null) { sServiceConnection = new CellBroadcastServiceConnection(); } mCellBroadcastServicePackage = getCellBroadcastServicePackage(); if (mCellBroadcastServicePackage != null) { mModuleCellBroadcastHandler = new Handler() { @Override public void handleMessage(@NonNull Message msg) { if (!mEnabled) { Log.d(TAG, "CB module is disabled."); return; } try { ICellBroadcastService cellBroadcastService = ICellBroadcastService.Stub.asInterface( sServiceConnection.mService); cellBroadcastService.handleGsmCellBroadcastSms(mPhone.getPhoneId(), (byte[]) ((AsyncResult) msg.obj).result); } catch (RemoteException e) { Log.e(TAG, "Failed to connect to default app: " + mCellBroadcastServicePackage + " err: " + e.toString()); mLocalLog.log("Failed to connect to default app: " + mCellBroadcastServicePackage + " err: " + e.toString()); mContext.unbindService(sServiceConnection); sServiceConnection = null; } } }; Intent intent = new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE); intent.setPackage(mCellBroadcastServicePackage); if (sServiceConnection.mService == null) { mContext.bindService(intent, sServiceConnection, Context.BIND_AUTO_CREATE); } mPhone.mCi.setOnNewGsmBroadcastSms(mModuleCellBroadcastHandler, EVENT_NEW_SMS_CB, null); } else { Log.e(TAG, "Unable to bind service; no cell broadcast service found"); mLocalLog.log("Unable to bind service; no cell broadcast service found"); } } /** Returns the package name of the cell broadcast service, or null if there is none. */ private String getCellBroadcastServicePackage() { return mContext.getResources().getString( com.android.internal.R.string.cellbroadcast_default_package); } private class CellBroadcastServiceConnection implements ServiceConnection { IBinder mService; @Override public void onServiceConnected(ComponentName className, IBinder service) { Log.d(TAG, "connected to CellBroadcastService"); this.mService = service; } @Override public void onServiceDisconnected(ComponentName arg0) { Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly"); this.mService = null; } } /** * Triggered with `adb shell dumpsys isms` */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("CellBroadcastServiceManager:"); pw.println(" mEnabled=" + mEnabled); pw.println(" mCellBroadcastServicePackage=" + mCellBroadcastServicePackage); mLocalLog.dump(fd, pw, args); pw.flush(); } }
src/java/com/android/internal/telephony/InboundSmsHandler.java +0 −1 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.IPackageManager; import android.content.pm.UserInfo; import android.database.Cursor; import android.database.Cursor; import android.database.SQLException; import android.database.SQLException; import android.net.Uri; import android.net.Uri; Loading
src/java/com/android/internal/telephony/SmsController.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -551,6 +551,9 @@ public class SmsController extends ISmsImplBase { } } } } /** * Triggered by `adb shell dumpsys isms` */ @Override @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!checkDumpPermission(mContext, LOG_TAG, pw)) { if (!checkDumpPermission(mContext, LOG_TAG, pw)) { Loading
src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java +145 −3 Original line number Original line Diff line number Diff line Loading @@ -17,10 +17,15 @@ package com.android.internal.telephony.gsm; package com.android.internal.telephony.gsm; import android.app.Activity; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncResult; import android.os.Message; import android.os.Message; import android.provider.Telephony.Sms.Intents; import android.provider.Telephony.Sms.Intents; import com.android.internal.telephony.CellBroadcastServiceManager; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.InboundSmsHandler; import com.android.internal.telephony.InboundSmsHandler; import com.android.internal.telephony.Phone; import com.android.internal.telephony.Phone; Loading @@ -31,24 +36,149 @@ import com.android.internal.telephony.SmsStorageMonitor; import com.android.internal.telephony.VisualVoicemailSmsFilter; import com.android.internal.telephony.VisualVoicemailSmsFilter; import com.android.internal.telephony.uicc.UsimServiceTable; 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 * 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 * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been */ */ public class GsmInboundSmsHandler extends InboundSmsHandler { public class GsmInboundSmsHandler extends InboundSmsHandler { private static BroadcastReceiver sTestBroadcastReceiver; /** Handler for SMS-PP data download messages to UICC. */ /** Handler for SMS-PP data download messages to UICC. */ private final UsimDataDownloadHandler mDataDownloadHandler; 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. * Create a new GSM inbound SMS handler. */ */ private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor, private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor, Phone phone) { Phone phone) { super("GsmInboundSmsHandler", context, storageMonitor, phone, super("GsmInboundSmsHandler", context, storageMonitor, phone, null); GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone)); phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId()); mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId()); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); if (sEnableCbModule) { mCellBroadcastServiceManager.enable(); } else { mCellBroadcastHandler = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone); } if (TEST_MODE) { sTestBroadcastReceiver = new GsmCbTestBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(TEST_ACTION); filter.addAction(TOGGLE_CB_MODULE); context.registerReceiver(sTestBroadcastReceiver, filter); } } /** * A broadcast receiver used for testing emergency cell broadcasts. To trigger test GSM cell * broadcasts with adb run e.g: * * adb shell am broadcast -a com.android.internal.telephony.gsm.TEST_TRIGGER_CELL_BROADCAST \ * --es pdu_string 0000110011010D0A5BAE57CE770C531790E85C716CBF3044573065B9306757309707767 \ * A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09000000000000000 \ * 0000000000000 * * adb shell am broadcast -a com.android.internal.telephony.gsm.TEST_TRIGGER_CELL_BROADCAST \ * --es pdu_string 0000110011010D0A5BAE57CE770C531790E85C716CBF3044573065B9306757309707767 \ * A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09000000000000000 \ * 0000000000000 --ei phone_id 0 * * 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 */ private class GsmCbTestBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { logd("Received test intent action=" + intent.getAction()); if (intent.getAction() == TEST_ACTION) { byte[] smsPdu = intent.getByteArrayExtra("pdu"); if (smsPdu == null) { String pduString = intent.getStringExtra("pdu_string"); smsPdu = decodeHexString(pduString); } if (smsPdu == null) { log("No pdu or pdu_string extra, ignoring CB test intent"); return; } // 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; } Message m = Message.obtain(); AsyncResult.forMessage(m, smsPdu, null); if (sEnableCbModule) { mCellBroadcastServiceManager.sendMessageToHandler(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"); mPhone.mCi.unSetOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler()); mCellBroadcastServiceManager.enable(); } else { log("enabling legacy platform CB handling"); mCellBroadcastServiceManager.disable(); if (mCellBroadcastHandler == null) { mCellBroadcastHandler = GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, mPhone); } mPhone.mCi.setOnNewGsmBroadcastSms(mCellBroadcastHandler.getHandler(), 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; } } /** /** Loading @@ -57,6 +187,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { @Override @Override protected void onQuitting() { protected void onQuitting() { mPhone.mCi.unSetOnNewGsmSms(getHandler()); mPhone.mCi.unSetOnNewGsmSms(getHandler()); mCellBroadcastServiceManager.disable(); mCellBroadcastHandler.dispose(); mCellBroadcastHandler.dispose(); if (DBG) log("unregistered for 3GPP SMS"); if (DBG) log("unregistered for 3GPP SMS"); Loading @@ -75,6 +206,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { /** /** * Return true if this handler is for 3GPP2 messages; false for 3GPP format. * Return true if this handler is for 3GPP2 messages; false for 3GPP format. * * @return false (3GPP) * @return false (3GPP) */ */ @Override @Override Loading Loading @@ -158,6 +290,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { /** /** * Send an acknowledge message. * Send an acknowledge message. * * @param success indicates that last message was successfully received. * @param success indicates that last message was successfully received. * @param result result code indicating any error * @param result result code indicating any error * @param response callback message sent when operation completes. * @param response callback message sent when operation completes. Loading @@ -169,6 +302,7 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { /** /** * Convert Android result code to 3GPP SMS failure cause. * Convert Android result code to 3GPP SMS failure cause. * * @param rc the Android SMS intent result value * @param rc the Android SMS intent result value * @return 0 for success, or a 3GPP SMS failure cause value * @return 0 for success, or a 3GPP SMS failure cause value */ */ Loading Loading @@ -201,4 +335,12 @@ public class GsmInboundSmsHandler extends InboundSmsHandler { mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), mMetrics.writeIncomingVoiceMailSms(mPhone.getPhoneId(), android.telephony.SmsMessage.FORMAT_3GPP); 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 +2 −2 Original line number Original line Diff line number Diff line Loading @@ -770,8 +770,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest { // verify that a broadcast receiver is registered for current user (user == null) based on // verify that a broadcast receiver is registered for current user (user == null) based on // implementation in ContextFixture // implementation in ContextFixture verify(mContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq((UserHandle)null), verify(mContext, times(2)).registerReceiverAsUser(any(BroadcastReceiver.class), any(IntentFilter.class), eq((String)null), eq((Handler)null)); eq((UserHandle)null), any(IntentFilter.class), eq((String)null), eq((Handler)null)); // wait for ScanRawTableThread // wait for ScanRawTableThread waitForMs(100); waitForMs(100); Loading