Loading src/java/com/android/internal/telephony/DefaultPhoneNotifier.java +6 −3 Original line number Diff line number Diff line Loading @@ -70,11 +70,14 @@ public class DefaultPhoneNotifier implements PhoneNotifier { @Override public void notifyServiceState(Phone sender) { ServiceState ss = sender.getServiceState(); notifyServiceStateForSubId(sender, sender.getServiceState(), sender.getSubId()); } @Override public void notifyServiceStateForSubId(Phone sender, ServiceState ss, int subId) { int phoneId = sender.getPhoneId(); int subId = sender.getSubId(); Rlog.d(LOG_TAG, "notifyServiceState: mRegistryMgr=" + mTelephonyRegistryMgr + " ss=" Rlog.d(LOG_TAG, "notifyServiceStateForSubId: mRegistryMgr=" + mTelephonyRegistryMgr + " ss=" + ss + " sender=" + sender + " phondId=" + phoneId + " subId=" + subId); if (ss == null) { ss = new ServiceState(); Loading src/java/com/android/internal/telephony/GsmCdmaPhone.java +4 −0 Original line number Diff line number Diff line Loading @@ -848,6 +848,10 @@ public class GsmCdmaPhone extends Phone { super.notifyServiceStateChangedP(ss); } void notifyServiceStateChangedForSubId(ServiceState ss, int subId) { super.notifyServiceStateChangedPForSubId(ss, subId); } /** * Notify that the cell location has changed. * Loading src/java/com/android/internal/telephony/InboundSmsHandler.java +195 −75 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.provider.Telephony.Sms.Intents.RESULT_SMS_NULL_PDU; import static android.service.carrier.CarrierMessagingService.RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE; import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; import android.annotation.Nullable; import android.app.Activity; import android.app.AppOpsManager; import android.app.BroadcastOptions; Loading Loading @@ -83,6 +84,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; /** Loading Loading @@ -163,7 +165,7 @@ public abstract class InboundSmsHandler extends StateMachine { public static final int EVENT_BROADCAST_SMS = 2; /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */ private static final int EVENT_BROADCAST_COMPLETE = 3; public static final int EVENT_BROADCAST_COMPLETE = 3; /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */ private static final int EVENT_RETURN_TO_IDLE = 4; Loading Loading @@ -259,6 +261,8 @@ public abstract class InboundSmsHandler extends StateMachine { others in order to update metrics. */ private boolean mLastSmsWasInjected = false; private List<SmsFilter> mSmsFilters; /** * Create a new SMS broadcast helper. * @param name the class name for logging Loading Loading @@ -288,6 +292,8 @@ public abstract class InboundSmsHandler extends StateMachine { (PowerWhitelistManager) mContext.getSystemService(Context.POWER_WHITELIST_MANAGER); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); mSmsFilters = createDefaultSmsFilters(); addState(mDefaultState); addState(mStartupState, mDefaultState); addState(mIdleState, mDefaultState); Loading Loading @@ -1050,6 +1056,15 @@ public abstract class InboundSmsHandler extends StateMachine { } } // Always invoke SMS filters, even if the number ends up being blocked, to prevent // surprising bugs due to blocking numbers that happen to be used for visual voicemail SMS // or other carrier system messages. boolean filterInvoked = filterSms( pdus, destPort, tracker, resultReceiver, true /* userUnlocked */, block); if (!filterInvoked) { // Block now if the filter wasn't invoked. Otherwise, it will be the responsibility of // the filter to delete the SMS once processing completes. if (block) { deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), DELETE_PERMANENTLY); Loading @@ -1058,10 +1073,6 @@ public abstract class InboundSmsHandler extends StateMachine { return false; } boolean filterInvoked = filterSms( pdus, destPort, tracker, resultReceiver, true /* userUnlocked */); if (!filterInvoked) { dispatchSmsDeliveryIntent(pdus, format, destPort, resultReceiver, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId()); } Loading @@ -1087,7 +1098,8 @@ public abstract class InboundSmsHandler extends StateMachine { if (destPort == -1) { // This is a regular SMS - hand it to the carrier or system app for filtering. boolean filterInvoked = filterSms( pdus, destPort, tracker, resultReceiver, false /* userUnlocked */); pdus, destPort, tracker, resultReceiver, false /* userUnlocked */, false /* block */); if (filterInvoked) { // filter invoked, wait for it to return the result. return true; Loading Loading @@ -1135,53 +1147,100 @@ public abstract class InboundSmsHandler extends StateMachine { } /** * Filters the SMS. * Creates the default filters used to filter SMS messages. * * <p>currently 3 filters exists: the carrier package, the system package, and the * VisualVoicemailSmsFilter. * <p>Currently 3 filters exist: the carrier package, the VisualVoicemailSmsFilter, and the * missed incoming call SMS filter. * * <p>The filtering process is: * * <p>If the carrier package exists, the SMS will be filtered with it first. If the carrier * package did not drop the SMS, then the VisualVoicemailSmsFilter will filter it in the * callback. * * <p>If the carrier package does not exists, we will let the VisualVoicemailSmsFilter filter * it. If the SMS passed the filter, then we will try to find the system package to do the * filtering. * * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise. * <p>Since the carrier filter is asynchronous, if a message passes through the carrier filter, * the remaining filters will be applied in the callback. */ private boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked) { private List<SmsFilter> createDefaultSmsFilters() { List<SmsFilter> smsFilters = new ArrayList<>(3); smsFilters.add( (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) -> { CarrierServicesSmsFilterCallback filterCallback = new CarrierServicesSmsFilterCallback( pdus, destPort, tracker.getFormat(), resultReceiver, userUnlocked, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId()); pdus, destPort, tracker, tracker.getFormat(), resultReceiver, userUnlocked, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId(), block, remainingFilters); CarrierServicesSmsFilter carrierServicesFilter = new CarrierServicesSmsFilter( mContext, mPhone, pdus, destPort, tracker.getFormat(), filterCallback, getName() + "::CarrierServicesSmsFilter", mCarrierServiceLocalLog, tracker.getMessageId()); filterCallback, getName() + "::CarrierServicesSmsFilter", mCarrierServiceLocalLog, tracker.getMessageId()); if (carrierServicesFilter.filter()) { log("filterSms: SMS is being handled by carrier service", tracker.getMessageId()); log("SMS is being handled by carrier service", tracker.getMessageId()); return true; } else { return false; } }); smsFilters.add( (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) -> { if (VisualVoicemailSmsFilter.filter( mContext, pdus, tracker.getFormat(), destPort, tracker.getSubId())) { logWithLocalLog("filterSms: Visual voicemail SMS dropped", tracker.getMessageId()); dropSms(resultReceiver); logWithLocalLog("Visual voicemail SMS dropped", tracker.getMessageId()); dropFilteredSms(tracker, resultReceiver, block); return true; } return false; }); smsFilters.add( (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) -> { MissedIncomingCallSmsFilter missedIncomingCallSmsFilter = new MissedIncomingCallSmsFilter(mPhone); if (missedIncomingCallSmsFilter.filter(pdus, tracker.getFormat())) { logWithLocalLog("filterSms: Missed incoming call SMS received", tracker.getMessageId()); dropSms(resultReceiver); logWithLocalLog("Missed incoming call SMS received", tracker.getMessageId()); dropFilteredSms(tracker, resultReceiver, block); return true; } return false; }); return smsFilters; } private void dropFilteredSms( InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean block) { if (block) { deleteFromRawTable( tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), DELETE_PERMANENTLY); sendMessage(EVENT_BROADCAST_COMPLETE); } else { dropSms(resultReceiver); } } /** * Filters the SMS. * * <p>Each filter in {@link #mSmsFilters} is invoked sequentially. If any filter returns true, * this method returns true and subsequent filters are ignored. * * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise. */ private boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block) { return filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, mSmsFilters); } private static boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, List<SmsFilter> filters) { ListIterator<SmsFilter> iterator = filters.listIterator(); while (iterator.hasNext()) { SmsFilter smsFilter = iterator.next(); if (smsFilter.filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, filters.subList(iterator.nextIndex(), filters.size()))) { return true; } } return false; } Loading Loading @@ -1526,7 +1585,8 @@ public abstract class InboundSmsHandler extends StateMachine { * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and * logs the broadcast duration (as an error if the other receivers were especially slow). */ private final class SmsBroadcastReceiver extends BroadcastReceiver { @VisibleForTesting public final class SmsBroadcastReceiver extends BroadcastReceiver { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private final String mDeleteWhere; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading Loading @@ -1611,37 +1671,64 @@ public abstract class InboundSmsHandler extends StateMachine { CarrierServicesSmsFilter.CarrierServicesSmsFilterCallbackInterface { private final byte[][] mPdus; private final int mDestPort; private final InboundSmsTracker mTracker; private final String mSmsFormat; private final SmsBroadcastReceiver mSmsBroadcastReceiver; private final boolean mUserUnlocked; private final boolean mIsClass0; private final int mSubId; private final long mMessageId; private final boolean mBlock; private final List<SmsFilter> mRemainingFilters; CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked, boolean isClass0, int subId, long messageId) { CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, InboundSmsTracker tracker, String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked, boolean isClass0, int subId, long messageId, boolean block, List<SmsFilter> remainingFilters) { mPdus = pdus; mDestPort = destPort; mTracker = tracker; mSmsFormat = smsFormat; mSmsBroadcastReceiver = smsBroadcastReceiver; mUserUnlocked = userUnlocked; mIsClass0 = isClass0; mSubId = subId; mMessageId = messageId; mBlock = block; mRemainingFilters = remainingFilters; } @Override public void onFilterComplete(int result) { log("onFilterComplete: result is " + result, mMessageId); if ((result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) == 0) { if (VisualVoicemailSmsFilter.filter(mContext, mPdus, mSmsFormat, mDestPort, mSubId)) { logWithLocalLog("Visual voicemail SMS dropped", mMessageId); dropSms(mSmsBroadcastReceiver); boolean carrierRequestedDrop = (result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) != 0; if (carrierRequestedDrop) { // Carrier app asked the platform to drop the SMS. Drop it from the database and // complete processing. dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock); return; } boolean filterInvoked = filterSms(mPdus, mDestPort, mTracker, mSmsBroadcastReceiver, mUserUnlocked, mBlock, mRemainingFilters); if (filterInvoked) { // A remaining filter has assumed responsibility for further message processing. return; } // Now that all filters have been invoked, drop the message if it is blocked. // TODO(b/156910035): Remove mUserUnlocked once we stop showing the new message // notification for blocked numbers. if (mUserUnlocked && mBlock) { log("onFilterComplete: dropping message as the sender is blocked", mTracker.getMessageId()); dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock); return; } // Message matched no filters and is not blocked, so complete processing. if (mUserUnlocked) { dispatchSmsDeliveryIntent( mPdus, mSmsFormat, mDestPort, mSmsBroadcastReceiver, mIsClass0, mSubId, Loading @@ -1655,10 +1742,6 @@ public abstract class InboundSmsHandler extends StateMachine { } sendMessage(EVENT_BROADCAST_COMPLETE); } } else { // Drop this SMS. dropSms(mSmsBroadcastReceiver); } } } Loading Loading @@ -1826,6 +1909,20 @@ public abstract class InboundSmsHandler extends StateMachine { mWakeLockTimeout = timeOut; } /** * Set the SMS filters used by {@link #filterSms} for testing purposes. * * @param smsFilters List of SMS filters, or null to restore the default filters. */ @VisibleForTesting public void setSmsFiltersForTesting(@Nullable List<SmsFilter> smsFilters) { if (smsFilters == null) { mSmsFilters = createDefaultSmsFilters(); } else { mSmsFilters = smsFilters; } } /** * Handler for the broadcast sent when the new message notification is clicked. It launches the * default SMS app. Loading Loading @@ -1905,4 +2002,27 @@ public abstract class InboundSmsHandler extends StateMachine { } } } /** A filter for incoming messages allowing the normal processing flow to be skipped. */ @VisibleForTesting public interface SmsFilter { /** * Returns true if a filter is invoked and the SMS processing flow should be diverted, false * otherwise. * * <p>If the filter can immediately determine that the message matches, it must call * {@link #dropFilteredSms} to drop the message from the database once it has been * processed. * * <p>If the filter must perform some asynchronous work to determine if the message matches, * it should return true to defer processing. Once it has made a determination, if it finds * the message matches, it must call {@link #dropFilteredSms}. If the message does not * match, it must be passed through {@code remainingFilters} and either dropped if the * remaining filters all return false or if {@code block} is true, or else it must be * broadcast. */ boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, List<SmsFilter> remainingFilters); } } src/java/com/android/internal/telephony/MultiSimSettingController.java +18 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncResult; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelUuid; import android.provider.Settings; Loading Loading @@ -232,6 +233,7 @@ public class MultiSimSettingController extends Handler { * Notify subscription info change. */ public void notifySubscriptionInfoChanged() { log("notifySubscriptionInfoChanged"); obtainMessage(EVENT_SUBSCRIPTION_INFO_CHANGED).sendToTarget(); } Loading Loading @@ -337,6 +339,22 @@ public class MultiSimSettingController extends Handler { reEvaluateAll(); } /** * This method is called when a phone object is removed (for example when going from multi-sim * to single-sim). * NOTE: This method does not post a message to self, instead it calls reEvaluateAll() directly. * so it should only be called from the main thread. The reason is to update defaults asap * after multi_sim_config property has been updated (see b/163582235). */ public void onPhoneRemoved() { if (DBG) log("onPhoneRemoved"); if (Looper.myLooper() != this.getLooper()) { throw new RuntimeException("This method must be called from the same looper as " + "MultiSimSettingController."); } reEvaluateAll(); } /** * Called when carrier config changes on any phone. */ Loading src/java/com/android/internal/telephony/Phone.java +11 −0 Original line number Diff line number Diff line Loading @@ -1702,6 +1702,17 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { mNotifier.notifyServiceState(this); } /** * Version of notifyServiceStateChangedP which allows us to specify the subId. This is used when * we send out a final ServiceState update when a phone's subId becomes invalid. */ protected void notifyServiceStateChangedPForSubId(ServiceState ss, int subId) { AsyncResult ar = new AsyncResult(null, ss, null); mServiceStateRegistrants.notifyRegistrants(ar); mNotifier.notifyServiceStateForSubId(this, ss, subId); } /** * If this is a simulated phone interface, returns a SimulatedRadioControl. * @return SimulatedRadioControl if this is a simulated interface; Loading Loading
src/java/com/android/internal/telephony/DefaultPhoneNotifier.java +6 −3 Original line number Diff line number Diff line Loading @@ -70,11 +70,14 @@ public class DefaultPhoneNotifier implements PhoneNotifier { @Override public void notifyServiceState(Phone sender) { ServiceState ss = sender.getServiceState(); notifyServiceStateForSubId(sender, sender.getServiceState(), sender.getSubId()); } @Override public void notifyServiceStateForSubId(Phone sender, ServiceState ss, int subId) { int phoneId = sender.getPhoneId(); int subId = sender.getSubId(); Rlog.d(LOG_TAG, "notifyServiceState: mRegistryMgr=" + mTelephonyRegistryMgr + " ss=" Rlog.d(LOG_TAG, "notifyServiceStateForSubId: mRegistryMgr=" + mTelephonyRegistryMgr + " ss=" + ss + " sender=" + sender + " phondId=" + phoneId + " subId=" + subId); if (ss == null) { ss = new ServiceState(); Loading
src/java/com/android/internal/telephony/GsmCdmaPhone.java +4 −0 Original line number Diff line number Diff line Loading @@ -848,6 +848,10 @@ public class GsmCdmaPhone extends Phone { super.notifyServiceStateChangedP(ss); } void notifyServiceStateChangedForSubId(ServiceState ss, int subId) { super.notifyServiceStateChangedPForSubId(ss, subId); } /** * Notify that the cell location has changed. * Loading
src/java/com/android/internal/telephony/InboundSmsHandler.java +195 −75 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.provider.Telephony.Sms.Intents.RESULT_SMS_NULL_PDU; import static android.service.carrier.CarrierMessagingService.RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE; import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; import android.annotation.Nullable; import android.app.Activity; import android.app.AppOpsManager; import android.app.BroadcastOptions; Loading Loading @@ -83,6 +84,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; /** Loading Loading @@ -163,7 +165,7 @@ public abstract class InboundSmsHandler extends StateMachine { public static final int EVENT_BROADCAST_SMS = 2; /** Message from resultReceiver notifying {@link WaitingState} of a completed broadcast. */ private static final int EVENT_BROADCAST_COMPLETE = 3; public static final int EVENT_BROADCAST_COMPLETE = 3; /** Sent on exit from {@link WaitingState} to return to idle after sending all broadcasts. */ private static final int EVENT_RETURN_TO_IDLE = 4; Loading Loading @@ -259,6 +261,8 @@ public abstract class InboundSmsHandler extends StateMachine { others in order to update metrics. */ private boolean mLastSmsWasInjected = false; private List<SmsFilter> mSmsFilters; /** * Create a new SMS broadcast helper. * @param name the class name for logging Loading Loading @@ -288,6 +292,8 @@ public abstract class InboundSmsHandler extends StateMachine { (PowerWhitelistManager) mContext.getSystemService(Context.POWER_WHITELIST_MANAGER); mCellBroadcastServiceManager = new CellBroadcastServiceManager(context, phone); mSmsFilters = createDefaultSmsFilters(); addState(mDefaultState); addState(mStartupState, mDefaultState); addState(mIdleState, mDefaultState); Loading Loading @@ -1050,6 +1056,15 @@ public abstract class InboundSmsHandler extends StateMachine { } } // Always invoke SMS filters, even if the number ends up being blocked, to prevent // surprising bugs due to blocking numbers that happen to be used for visual voicemail SMS // or other carrier system messages. boolean filterInvoked = filterSms( pdus, destPort, tracker, resultReceiver, true /* userUnlocked */, block); if (!filterInvoked) { // Block now if the filter wasn't invoked. Otherwise, it will be the responsibility of // the filter to delete the SMS once processing completes. if (block) { deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), DELETE_PERMANENTLY); Loading @@ -1058,10 +1073,6 @@ public abstract class InboundSmsHandler extends StateMachine { return false; } boolean filterInvoked = filterSms( pdus, destPort, tracker, resultReceiver, true /* userUnlocked */); if (!filterInvoked) { dispatchSmsDeliveryIntent(pdus, format, destPort, resultReceiver, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId()); } Loading @@ -1087,7 +1098,8 @@ public abstract class InboundSmsHandler extends StateMachine { if (destPort == -1) { // This is a regular SMS - hand it to the carrier or system app for filtering. boolean filterInvoked = filterSms( pdus, destPort, tracker, resultReceiver, false /* userUnlocked */); pdus, destPort, tracker, resultReceiver, false /* userUnlocked */, false /* block */); if (filterInvoked) { // filter invoked, wait for it to return the result. return true; Loading Loading @@ -1135,53 +1147,100 @@ public abstract class InboundSmsHandler extends StateMachine { } /** * Filters the SMS. * Creates the default filters used to filter SMS messages. * * <p>currently 3 filters exists: the carrier package, the system package, and the * VisualVoicemailSmsFilter. * <p>Currently 3 filters exist: the carrier package, the VisualVoicemailSmsFilter, and the * missed incoming call SMS filter. * * <p>The filtering process is: * * <p>If the carrier package exists, the SMS will be filtered with it first. If the carrier * package did not drop the SMS, then the VisualVoicemailSmsFilter will filter it in the * callback. * * <p>If the carrier package does not exists, we will let the VisualVoicemailSmsFilter filter * it. If the SMS passed the filter, then we will try to find the system package to do the * filtering. * * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise. * <p>Since the carrier filter is asynchronous, if a message passes through the carrier filter, * the remaining filters will be applied in the callback. */ private boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked) { private List<SmsFilter> createDefaultSmsFilters() { List<SmsFilter> smsFilters = new ArrayList<>(3); smsFilters.add( (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) -> { CarrierServicesSmsFilterCallback filterCallback = new CarrierServicesSmsFilterCallback( pdus, destPort, tracker.getFormat(), resultReceiver, userUnlocked, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId()); pdus, destPort, tracker, tracker.getFormat(), resultReceiver, userUnlocked, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId(), block, remainingFilters); CarrierServicesSmsFilter carrierServicesFilter = new CarrierServicesSmsFilter( mContext, mPhone, pdus, destPort, tracker.getFormat(), filterCallback, getName() + "::CarrierServicesSmsFilter", mCarrierServiceLocalLog, tracker.getMessageId()); filterCallback, getName() + "::CarrierServicesSmsFilter", mCarrierServiceLocalLog, tracker.getMessageId()); if (carrierServicesFilter.filter()) { log("filterSms: SMS is being handled by carrier service", tracker.getMessageId()); log("SMS is being handled by carrier service", tracker.getMessageId()); return true; } else { return false; } }); smsFilters.add( (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) -> { if (VisualVoicemailSmsFilter.filter( mContext, pdus, tracker.getFormat(), destPort, tracker.getSubId())) { logWithLocalLog("filterSms: Visual voicemail SMS dropped", tracker.getMessageId()); dropSms(resultReceiver); logWithLocalLog("Visual voicemail SMS dropped", tracker.getMessageId()); dropFilteredSms(tracker, resultReceiver, block); return true; } return false; }); smsFilters.add( (pdus, destPort, tracker, resultReceiver, userUnlocked, block, remainingFilters) -> { MissedIncomingCallSmsFilter missedIncomingCallSmsFilter = new MissedIncomingCallSmsFilter(mPhone); if (missedIncomingCallSmsFilter.filter(pdus, tracker.getFormat())) { logWithLocalLog("filterSms: Missed incoming call SMS received", tracker.getMessageId()); dropSms(resultReceiver); logWithLocalLog("Missed incoming call SMS received", tracker.getMessageId()); dropFilteredSms(tracker, resultReceiver, block); return true; } return false; }); return smsFilters; } private void dropFilteredSms( InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean block) { if (block) { deleteFromRawTable( tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), DELETE_PERMANENTLY); sendMessage(EVENT_BROADCAST_COMPLETE); } else { dropSms(resultReceiver); } } /** * Filters the SMS. * * <p>Each filter in {@link #mSmsFilters} is invoked sequentially. If any filter returns true, * this method returns true and subsequent filters are ignored. * * @return true if a filter is invoked and the SMS processing flow is diverted, false otherwise. */ private boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block) { return filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, mSmsFilters); } private static boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, List<SmsFilter> filters) { ListIterator<SmsFilter> iterator = filters.listIterator(); while (iterator.hasNext()) { SmsFilter smsFilter = iterator.next(); if (smsFilter.filterSms(pdus, destPort, tracker, resultReceiver, userUnlocked, block, filters.subList(iterator.nextIndex(), filters.size()))) { return true; } } return false; } Loading Loading @@ -1526,7 +1585,8 @@ public abstract class InboundSmsHandler extends StateMachine { * Handler for an {@link InboundSmsTracker} broadcast. Deletes PDUs from the raw table and * logs the broadcast duration (as an error if the other receivers were especially slow). */ private final class SmsBroadcastReceiver extends BroadcastReceiver { @VisibleForTesting public final class SmsBroadcastReceiver extends BroadcastReceiver { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private final String mDeleteWhere; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading Loading @@ -1611,37 +1671,64 @@ public abstract class InboundSmsHandler extends StateMachine { CarrierServicesSmsFilter.CarrierServicesSmsFilterCallbackInterface { private final byte[][] mPdus; private final int mDestPort; private final InboundSmsTracker mTracker; private final String mSmsFormat; private final SmsBroadcastReceiver mSmsBroadcastReceiver; private final boolean mUserUnlocked; private final boolean mIsClass0; private final int mSubId; private final long mMessageId; private final boolean mBlock; private final List<SmsFilter> mRemainingFilters; CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked, boolean isClass0, int subId, long messageId) { CarrierServicesSmsFilterCallback(byte[][] pdus, int destPort, InboundSmsTracker tracker, String smsFormat, SmsBroadcastReceiver smsBroadcastReceiver, boolean userUnlocked, boolean isClass0, int subId, long messageId, boolean block, List<SmsFilter> remainingFilters) { mPdus = pdus; mDestPort = destPort; mTracker = tracker; mSmsFormat = smsFormat; mSmsBroadcastReceiver = smsBroadcastReceiver; mUserUnlocked = userUnlocked; mIsClass0 = isClass0; mSubId = subId; mMessageId = messageId; mBlock = block; mRemainingFilters = remainingFilters; } @Override public void onFilterComplete(int result) { log("onFilterComplete: result is " + result, mMessageId); if ((result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) == 0) { if (VisualVoicemailSmsFilter.filter(mContext, mPdus, mSmsFormat, mDestPort, mSubId)) { logWithLocalLog("Visual voicemail SMS dropped", mMessageId); dropSms(mSmsBroadcastReceiver); boolean carrierRequestedDrop = (result & CarrierMessagingService.RECEIVE_OPTIONS_DROP) != 0; if (carrierRequestedDrop) { // Carrier app asked the platform to drop the SMS. Drop it from the database and // complete processing. dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock); return; } boolean filterInvoked = filterSms(mPdus, mDestPort, mTracker, mSmsBroadcastReceiver, mUserUnlocked, mBlock, mRemainingFilters); if (filterInvoked) { // A remaining filter has assumed responsibility for further message processing. return; } // Now that all filters have been invoked, drop the message if it is blocked. // TODO(b/156910035): Remove mUserUnlocked once we stop showing the new message // notification for blocked numbers. if (mUserUnlocked && mBlock) { log("onFilterComplete: dropping message as the sender is blocked", mTracker.getMessageId()); dropFilteredSms(mTracker, mSmsBroadcastReceiver, mBlock); return; } // Message matched no filters and is not blocked, so complete processing. if (mUserUnlocked) { dispatchSmsDeliveryIntent( mPdus, mSmsFormat, mDestPort, mSmsBroadcastReceiver, mIsClass0, mSubId, Loading @@ -1655,10 +1742,6 @@ public abstract class InboundSmsHandler extends StateMachine { } sendMessage(EVENT_BROADCAST_COMPLETE); } } else { // Drop this SMS. dropSms(mSmsBroadcastReceiver); } } } Loading Loading @@ -1826,6 +1909,20 @@ public abstract class InboundSmsHandler extends StateMachine { mWakeLockTimeout = timeOut; } /** * Set the SMS filters used by {@link #filterSms} for testing purposes. * * @param smsFilters List of SMS filters, or null to restore the default filters. */ @VisibleForTesting public void setSmsFiltersForTesting(@Nullable List<SmsFilter> smsFilters) { if (smsFilters == null) { mSmsFilters = createDefaultSmsFilters(); } else { mSmsFilters = smsFilters; } } /** * Handler for the broadcast sent when the new message notification is clicked. It launches the * default SMS app. Loading Loading @@ -1905,4 +2002,27 @@ public abstract class InboundSmsHandler extends StateMachine { } } } /** A filter for incoming messages allowing the normal processing flow to be skipped. */ @VisibleForTesting public interface SmsFilter { /** * Returns true if a filter is invoked and the SMS processing flow should be diverted, false * otherwise. * * <p>If the filter can immediately determine that the message matches, it must call * {@link #dropFilteredSms} to drop the message from the database once it has been * processed. * * <p>If the filter must perform some asynchronous work to determine if the message matches, * it should return true to defer processing. Once it has made a determination, if it finds * the message matches, it must call {@link #dropFilteredSms}. If the message does not * match, it must be passed through {@code remainingFilters} and either dropped if the * remaining filters all return false or if {@code block} is true, or else it must be * broadcast. */ boolean filterSms(byte[][] pdus, int destPort, InboundSmsTracker tracker, SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block, List<SmsFilter> remainingFilters); } }
src/java/com/android/internal/telephony/MultiSimSettingController.java +18 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncResult; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelUuid; import android.provider.Settings; Loading Loading @@ -232,6 +233,7 @@ public class MultiSimSettingController extends Handler { * Notify subscription info change. */ public void notifySubscriptionInfoChanged() { log("notifySubscriptionInfoChanged"); obtainMessage(EVENT_SUBSCRIPTION_INFO_CHANGED).sendToTarget(); } Loading Loading @@ -337,6 +339,22 @@ public class MultiSimSettingController extends Handler { reEvaluateAll(); } /** * This method is called when a phone object is removed (for example when going from multi-sim * to single-sim). * NOTE: This method does not post a message to self, instead it calls reEvaluateAll() directly. * so it should only be called from the main thread. The reason is to update defaults asap * after multi_sim_config property has been updated (see b/163582235). */ public void onPhoneRemoved() { if (DBG) log("onPhoneRemoved"); if (Looper.myLooper() != this.getLooper()) { throw new RuntimeException("This method must be called from the same looper as " + "MultiSimSettingController."); } reEvaluateAll(); } /** * Called when carrier config changes on any phone. */ Loading
src/java/com/android/internal/telephony/Phone.java +11 −0 Original line number Diff line number Diff line Loading @@ -1702,6 +1702,17 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { mNotifier.notifyServiceState(this); } /** * Version of notifyServiceStateChangedP which allows us to specify the subId. This is used when * we send out a final ServiceState update when a phone's subId becomes invalid. */ protected void notifyServiceStateChangedPForSubId(ServiceState ss, int subId) { AsyncResult ar = new AsyncResult(null, ss, null); mServiceStateRegistrants.notifyRegistrants(ar); mNotifier.notifyServiceStateForSubId(this, ss, subId); } /** * If this is a simulated phone interface, returns a SimulatedRadioControl. * @return SimulatedRadioControl if this is a simulated interface; Loading