bug 如图
发送短信后,实际发送一条,界面显示发送两条,问题本质是发件箱数据中确实写入了两条。
2020-01-03 15:41:01.532 6736-6736/? D/cczSettingPreference: sms:: inbox 2020-01-03 15:41:01.547 6736-6736/? D/cczSettingPreference: threadId:: 1 result::0 2020-01-03 15:41:01.550 6736-6736/? D/cczSettingPreference: sms:: sent 2020-01-03 15:41:01.561 6736-6736/? D/cczSettingPreference: threadId:: 1 result::0 2020-01-03 15:41:01.562 6736-6736/? D/cczSettingPreference: threadId:: 1 result::0 2020-01-03 15:41:01.567 6736-6736/? D/cczSettingPreference: sms:: draft 2020-01-03 15:41:01.579 6736-6736/? D/cczSettingPreference: sms:: outbox 2020-01-03 15:41:01.592 6736-6736/? D/cczSettingPreference: sms:: failed 2020-01-03 15:41:01.604 6736-6736/? D/cczSettingPreference: sms:: queued
这个问题困扰了好久,经过3天的排查终于解决了,来整理下排查思路
一、先确定是 app 层的问题还是 framework 层问题(开始方向搞错了,浪费了两天时间,唉~)
二、简单理下短信发送流程
三、根据发件箱 URI 全局搜索
在网上找了个经典版短信app发送短信,是正常的,只写入一条已发送,由此简单判定不是framework的问题,后来证明是自己坑自己[笑哭]
在系统短信 Mms 源码中搜索如下关键字段
Telephony.Sms.CONTENT_URI
Telephony.Mms.Sent.CONTENT_URI;
Telephony.Sms.MESSAGE_TYPE_SENT
Telephony.Sms.moveMessageToFolder
几乎没找到相关的。简单说下短信发送流程,先将短信写入 queued 中,发送成功后移动到 MESSAGE_TYPE_SENT 中
注释 SmsReceiverService 中的 moveMessageToFolder( 方法,短信发送后会显示感叹号,而且数据库查不到这条短信。
开始复写了 moveMessageToFolder() 的逻辑一度以为已经修改好了,但其实根本不是这的问题
SqliteWrapper.update() 其实就是 Telephony.Sms.moveMessageToFolder() 的方法体
vendor\mediatek\proprietary\packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverService.java
@@ -517,11 +517,19 @@ public class SmsReceiverService extends Service implements ISmsReceiverServiceCa // so we shouldn't move it to other boxes.just keep it in failed box. if (smsType != Sms.MESSAGE_TYPE_FAILED) { //move sms from out box to sent box //cczheng add Log.e(TAG, "handleSmsSent: don't need move message "+ uri + " to sent folder"); /*ContentValues values = new ContentValues(3); values.put(Sms.TYPE, Sms.MESSAGE_TYPE_SENT); values.put(Sms.ERROR_CODE, error); values.put(Sms.READ, Integer.valueOf(0)); SqliteWrapper.update(getApplicationContext(), getContentResolver(), uri, values, null, null);*/ if (!Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_SENT, error)) { Log.e(TAG, "handleSmsSent: failed to move message " + uri + " to sent folder"); } } } } finally {
后来在framework 中找到 SMSDispatcher.java
frameworks\opt\telephony\src\java\com\android\internal\telephony\SMSDispatcher.java
private Uri persistSentMessageIfRequired(Context context, int messageType, int errorCode) { if (!mIsText || !mPersistMessage || !SmsApplication.shouldWriteMessageForPackage(mAppInfo.packageName, context)) { Rlog.d(TAG, "Persist SMS into packageName="+ mAppInfo.packageName); return null; } Rlog.d(TAG, "Persist SMS into " + (messageType == Sms.MESSAGE_TYPE_FAILED ? "FAILED" : "SENT")); final ContentValues values = new ContentValues(); values.put(Sms.SUBSCRIPTION_ID, mSubId); values.put(Sms.ADDRESS, mDestAddress); values.put(Sms.BODY, mFullMessageText); values.put(Sms.DATE, System.currentTimeMillis()); // milliseconds values.put(Sms.SEEN, 1); values.put(Sms.READ, 1); final String creator = mAppInfo != null ? mAppInfo.packageName : null; if (!TextUtils.isEmpty(creator)) { values.put(Sms.CREATOR, creator); } if (mDeliveryIntent != null) { values.put(Sms.STATUS, Telephony.Sms.STATUS_PENDING); } if (errorCode != 0) { values.put(Sms.ERROR_CODE, errorCode); } final long identity = Binder.clearCallingIdentity(); final ContentResolver resolver = context.getContentResolver(); try { final Uri uri = resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values); if (uri != null && messageType == Sms.MESSAGE_TYPE_FAILED) { // Since we can't persist a message directly into FAILED box, // we have to update the column after we persist it into SENT box. // The gap between the state change is tiny so I would not expect // it to cause any serious problem // TODO: we should add a "failed" URI for this in SmsProvider? final ContentValues updateValues = new ContentValues(1); updateValues.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED); resolver.update(uri, updateValues, null/*where*/, null/*selectionArgs*/); } return uri; } catch (Exception e) { Rlog.e(TAG, "writeOutboxMessage: Failed to persist outbox message", e); return null; } finally { Binder.restoreCallingIdentity(identity); } }
通过抓取MMS和经典版短信发送短信 radio log 比对
resolver.insert(Telephony.Sms.Sent.CONTENT_URI, values); 发现就是这货插入的发件箱,幕后真凶终于找到了。
MMS
01-01 08:03:39.403 1309 1309 D MtkGsmSMSDispatcher: Remove Tracker 01-01 08:03:39.403 1309 1309 D MtkGsmSMSDispatcher: mSTrackersQueue is empty 01-01 08:03:39.403 1309 1309 D SMSDispatcher: onSent isSinglePartOrLastPart=true 01-01 08:03:39.444 1309 3916 D SMSDispatcher: Persist SMS into SENT 01-01 08:03:39.502 1309 3916 E SmsApplication: com.mediatek.datatransfer does not have system signature 01-01 08:03:39.502 1309 3916 E SmsApplication: com.mediatek.op18.plugin does not have system signature 01-01 08:03:39.502 1309 3916 E SmsApplication: com.mediatek.apst.target does not have system signature 01-01 08:03:39.503 1309 3916 E SmsApplication: com.mediatek.backuprestore does not have system signature 01-01 08:03:39.505 1309 3916 E SmsApplication: com.mediatek.rcs.messageservice does not have system signature 01-01 08:03:39.505 1309 3916 E SmsApplication: com.android.mms does not have system signature 01-01 08:03:39.506 1309 1309 D SMSDispatcher: message reference number : 144 01-01 08:03:39.644 922 960 I AT : AT< +ECSQ: 15,53,1,1,1,-50,-352,7,19 (RIL_URC_READER, tid:0) 01-01 08:03:39.646 1133 1413 D RpNwSC : [0] Sig: gsm[0 53] c2k[55 90 120 -64 8] lte[99 88 12 47 2147483647] tds[2147483647] umts[0 0 0]
经典版短信
01-10 10:01:59.210 1368 1368 D MtkGsmSMSDispatcher: Remove Tracker 01-10 10:01:59.210 1368 1462 D RILJ : [4040]< RIL_REQUEST_IMS_SEND_SMS { mMessageRef = 147, mErrorCode = 0, mAckPdu = } [SUB0] 01-10 10:01:59.210 1368 1368 D MtkGsmSMSDispatcher: mSTrackersQueue is empty 01-10 10:01:59.210 1368 1368 D SMSDispatcher: onSent isSinglePartOrLastPart=true 01-10 10:01:59.218 1368 4708 D SMSDispatcher: Persist SMS into packageName=com.thinkyeah.message 01-10 10:01:59.218 1368 1368 D SMSDispatcher: message reference number : 147 01-10 10:02:00.000 769 3178 D MtkTelephonyRegistryEx: idMatchEx: rSubId=2147483647, subId=1, dSubId=1, rPhoneId=-1, phoneId=0
简单解决办法就是 persistSentMessageIfRequired() if 判断直接 return,bug就解决了