use of android.compat.annotation.UnsupportedAppUsage in project android_frameworks_opt_telephony by LineageOS.
the class InboundSmsHandler method processMessagePart.
/**
* Process the inbound SMS segment. If the message is complete, send it as an ordered
* broadcast to interested receivers and return true. If the message is a segment of an
* incomplete multi-part SMS, return false.
* @param tracker the tracker containing the message segment to process
* @return true if an ordered broadcast was sent; false if waiting for more message segments
*/
@UnsupportedAppUsage
private boolean processMessagePart(InboundSmsTracker tracker) {
int messageCount = tracker.getMessageCount();
byte[][] pdus;
long[] timestamps;
int destPort = tracker.getDestPort();
boolean block = false;
String address = tracker.getAddress();
// Do not process when the message count is invalid.
if (messageCount <= 0) {
loge("processMessagePart: returning false due to invalid message count " + messageCount, tracker.getMessageId());
return false;
}
if (messageCount == 1) {
// single-part message
pdus = new byte[][] { tracker.getPdu() };
timestamps = new long[] { tracker.getTimestamp() };
block = BlockChecker.isBlocked(mContext, tracker.getDisplayAddress(), null);
} else {
// multi-part message
Cursor cursor = null;
try {
// used by several query selection arguments
String refNumber = Integer.toString(tracker.getReferenceNumber());
String count = Integer.toString(tracker.getMessageCount());
// query for all segments and broadcast message if we have all the parts
String[] whereArgs = { address, refNumber, count };
cursor = mResolver.query(sRawUri, PDU_SEQUENCE_PORT_PROJECTION, tracker.getQueryForSegments(), whereArgs, null);
int cursorCount = cursor.getCount();
if (cursorCount < messageCount) {
// Wait for the other message parts to arrive. It's also possible for the last
// segment to arrive before processing the EVENT_BROADCAST_SMS for one of the
// earlier segments. In that case, the broadcast will be sent as soon as all
// segments are in the table, and any later EVENT_BROADCAST_SMS messages will
// get a row count of 0 and return.
log("processMessagePart: returning false. Only " + cursorCount + " of " + messageCount + " segments " + " have arrived. refNumber: " + refNumber, tracker.getMessageId());
return false;
}
// All the parts are in place, deal with them
pdus = new byte[messageCount][];
timestamps = new long[messageCount];
while (cursor.moveToNext()) {
// subtract offset to convert sequence to 0-based array index
int index = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(SEQUENCE_COLUMN)) - tracker.getIndexOffset();
// UserDataHeader is invalid.
if (index >= pdus.length || index < 0) {
loge(String.format("processMessagePart: invalid seqNumber = %d, messageCount = %d", index + tracker.getIndexOffset(), messageCount), tracker.getMessageId());
continue;
}
pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)));
// It's not a bad idea to prefer the port from the first segment in other cases.
if (index == 0 && !cursor.isNull(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(DESTINATION_PORT_COLUMN))) {
int port = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(DESTINATION_PORT_COLUMN));
// strip format flags and convert to real port number, or -1
port = InboundSmsTracker.getRealDestPort(port);
if (port != -1) {
destPort = port;
}
}
timestamps[index] = cursor.getLong(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(DATE_COLUMN));
// check if display address should be blocked or not
if (!block) {
// Depending on the nature of the gateway, the display origination address
// is either derived from the content of the SMS TP-OA field, or the TP-OA
// field contains a generic gateway address and the from address is added
// at the beginning in the message body. In that case only the first SMS
// (part of Multi-SMS) comes with the display originating address which
// could be used for block checking purpose.
block = BlockChecker.isBlocked(mContext, cursor.getString(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(DISPLAY_ADDRESS_COLUMN)), null);
}
}
log("processMessagePart: all " + messageCount + " segments " + " received. refNumber: " + refNumber, tracker.getMessageId());
} catch (SQLException e) {
loge("processMessagePart: Can't access multipart SMS database, id: " + tracker.getMessageId(), e);
return false;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
final boolean isWapPush = (destPort == SmsHeader.PORT_WAP_PUSH);
// At this point, all parts of the SMS are received. Update metrics for incoming SMS.
// WAP-PUSH messages are handled below to also keep track of the result of the processing.
String format = tracker.getFormat();
if (!isWapPush) {
mMetrics.writeIncomingSmsSession(mPhone.getPhoneId(), mLastSmsWasInjected, format, timestamps, block, tracker.getMessageId());
}
// Do not process null pdu(s). Check for that and return false in that case.
List<byte[]> pduList = Arrays.asList(pdus);
if (pduList.size() == 0 || pduList.contains(null)) {
String errorMsg = "processMessagePart: returning false due to " + (pduList.size() == 0 ? "pduList.size() == 0" : "pduList.contains(null)");
logeWithLocalLog(errorMsg, tracker.getMessageId());
return false;
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
if (isWapPush) {
for (byte[] pdu : pdus) {
// 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this
if (format == SmsConstants.FORMAT_3GPP) {
SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
if (msg != null) {
pdu = msg.getUserData();
} else {
loge("processMessagePart: SmsMessage.createFromPdu returned null", tracker.getMessageId());
mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), mLastSmsWasInjected, SmsConstants.FORMAT_3GPP, timestamps, false, tracker.getMessageId());
return false;
}
}
output.write(pdu, 0, pdu.length);
}
}
SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);
if (!mUserManager.isUserUnlocked()) {
log("processMessagePart: !isUserUnlocked; calling processMessagePartWithUserLocked. " + "Port: " + destPort, tracker.getMessageId());
return processMessagePartWithUserLocked(tracker, (isWapPush ? new byte[][] { output.toByteArray() } : pdus), destPort, resultReceiver);
}
if (isWapPush) {
int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this, address, tracker.getSubId(), tracker.getMessageId());
if (DBG) {
log("processMessagePart: dispatchWapPdu() returned " + result, tracker.getMessageId());
}
// needs to be ignored, so treating it as a success case.
if (result == Activity.RESULT_OK || result == Intents.RESULT_SMS_HANDLED) {
mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), mLastSmsWasInjected, format, timestamps, true, tracker.getMessageId());
} else {
mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), mLastSmsWasInjected, format, timestamps, false, tracker.getMessageId());
}
// result is Activity.RESULT_OK if an ordered broadcast was sent
if (result == Activity.RESULT_OK) {
return true;
} else {
deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), MARK_DELETED);
loge("processMessagePart: returning false as the ordered broadcast for WAP push " + "was not sent", tracker.getMessageId());
return false;
}
}
// 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) {
// the filter to delete the SMS once processing completes.
if (block) {
deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(), DELETE_PERMANENTLY);
log("processMessagePart: returning false as the phone number is blocked", tracker.getMessageId());
return false;
}
dispatchSmsDeliveryIntent(pdus, format, destPort, resultReceiver, tracker.isClass0(), tracker.getSubId(), tracker.getMessageId());
}
return true;
}
use of android.compat.annotation.UnsupportedAppUsage in project android_frameworks_opt_telephony by LineageOS.
the class InboundSmsHandler method writeInboxMessage.
/**
* Store a received SMS into Telephony provider
*
* @param intent The intent containing the received SMS
* @return The URI of written message
*/
@UnsupportedAppUsage
private Uri writeInboxMessage(Intent intent) {
final SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
if (messages == null || messages.length < 1) {
loge("Failed to parse SMS pdu");
return null;
}
// Sometimes, SmsMessage is null if it can’t be parsed correctly.
for (final SmsMessage sms : messages) {
if (sms == null) {
loge("Can’t write null SmsMessage");
return null;
}
}
final ContentValues values = parseSmsMessage(messages);
final long identity = Binder.clearCallingIdentity();
try {
return mContext.getContentResolver().insert(Telephony.Sms.Inbox.CONTENT_URI, values);
} catch (Exception e) {
loge("Failed to persist inbox message", e);
} finally {
Binder.restoreCallingIdentity(identity);
}
return null;
}
use of android.compat.annotation.UnsupportedAppUsage in project android_frameworks_opt_telephony by LineageOS.
the class InboundSmsHandler method handleSmsWhitelisting.
@UnsupportedAppUsage
private Bundle handleSmsWhitelisting(ComponentName target, boolean bgActivityStartAllowed) {
String pkgName;
String reason;
if (target != null) {
pkgName = target.getPackageName();
reason = "sms-app";
} else {
pkgName = mContext.getPackageName();
reason = "sms-broadcast";
}
BroadcastOptions bopts = null;
Bundle bundle = null;
if (bgActivityStartAllowed) {
bopts = BroadcastOptions.makeBasic();
bopts.setBackgroundActivityStartsAllowed(true);
bundle = bopts.toBundle();
}
long duration = mPowerWhitelistManager.whitelistAppTemporarilyForEvent(pkgName, PowerWhitelistManager.EVENT_SMS, reason);
if (bopts == null)
bopts = BroadcastOptions.makeBasic();
bopts.setTemporaryAppWhitelistDuration(duration);
bundle = bopts.toBundle();
return bundle;
}
use of android.compat.annotation.UnsupportedAppUsage in project android_frameworks_opt_telephony by LineageOS.
the class InboundSmsHandler method handleInjectSms.
/**
* This method is called when a new SMS PDU is injected into application framework.
* @param ar is the AsyncResult that has the SMS PDU to be injected.
*/
@UnsupportedAppUsage
private void handleInjectSms(AsyncResult ar) {
int result;
SmsDispatchersController.SmsInjectionCallback callback = null;
try {
callback = (SmsDispatchersController.SmsInjectionCallback) ar.userObj;
SmsMessage sms = (SmsMessage) ar.result;
if (sms == null) {
loge("Null injected sms");
result = RESULT_SMS_NULL_PDU;
} else {
mLastSmsWasInjected = true;
result = dispatchMessage(sms.mWrappedSmsMessage);
}
} catch (RuntimeException ex) {
loge("Exception dispatching message", ex);
result = RESULT_SMS_DISPATCH_FAILURE;
}
if (callback != null) {
callback.onSmsInjectedResult(result);
}
}
use of android.compat.annotation.UnsupportedAppUsage in project android_frameworks_opt_telephony by LineageOS.
the class IccSmsInterfaceManager method setCellBroadcastConfig.
@UnsupportedAppUsage
private boolean setCellBroadcastConfig(SmsBroadcastConfigInfo[] configs) {
if (DBG) {
log("Calling setGsmBroadcastConfig with " + configs.length + " configurations");
}
enforceNotOnHandlerThread("setCellBroadcastConfig");
synchronized (mLock) {
Message response = mHandler.obtainMessage(EVENT_SET_BROADCAST_CONFIG_DONE);
mSuccess = false;
mPhone.mCi.setGsmBroadcastConfig(configs, response);
try {
mLock.wait();
} catch (InterruptedException e) {
loge("interrupted while trying to set cell broadcast config");
}
}
return mSuccess;
}
Aggregations